blob: e3033959479f45701b0d6c3f78a9063d2ea6fcec [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
37
38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_table.h"
40#include "bgpd/bgp_aspath.h"
41#include "bgpd/bgp_route.h"
42#include "bgpd/bgp_dump.h"
43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_community.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_regex.h"
47#include "bgpd/bgp_clist.h"
48#include "bgpd/bgp_fsm.h"
49#include "bgpd/bgp_packet.h"
50#include "bgpd/bgp_zebra.h"
51#include "bgpd/bgp_open.h"
52#include "bgpd/bgp_filter.h"
53#include "bgpd/bgp_nexthop.h"
54#include "bgpd/bgp_damp.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_advertise.h"
57#include "bgpd/bgp_network.h"
58#include "bgpd/bgp_vty.h"
59#ifdef HAVE_SNMP
60#include "bgpd/bgp_snmp.h"
61#endif /* HAVE_SNMP */
62
63/* BGP process wide configuration. */
64static struct bgp_master bgp_master;
65
hasso18a6dce2004-10-03 18:18:34 +000066extern struct in_addr router_id_zebra;
67
paul718e3742002-12-13 20:15:29 +000068/* BGP process wide configuration pointer to export. */
69struct bgp_master *bm;
70
71/* BGP community-list. */
72struct community_list_handler *bgp_clist;
73
74/* BGP global flag manipulation. */
75int
76bgp_option_set (int flag)
77{
78 switch (flag)
79 {
80 case BGP_OPT_NO_FIB:
81 case BGP_OPT_MULTIPLE_INSTANCE:
82 case BGP_OPT_CONFIG_CISCO:
83 SET_FLAG (bm->options, flag);
84 break;
85 default:
86 return BGP_ERR_INVALID_FLAG;
87 break;
88 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
107 break;
108 }
109 return 0;
110}
111
112int
113bgp_option_check (int flag)
114{
115 return CHECK_FLAG (bm->options, flag);
116}
117
118/* BGP flag manipulation. */
119int
120bgp_flag_set (struct bgp *bgp, int flag)
121{
122 SET_FLAG (bgp->flags, flag);
123 return 0;
124}
125
126int
127bgp_flag_unset (struct bgp *bgp, int flag)
128{
129 UNSET_FLAG (bgp->flags, flag);
130 return 0;
131}
132
133int
134bgp_flag_check (struct bgp *bgp, int flag)
135{
136 return CHECK_FLAG (bgp->flags, flag);
137}
138
139/* Internal function to set BGP structure configureation flag. */
140static void
141bgp_config_set (struct bgp *bgp, int config)
142{
143 SET_FLAG (bgp->config, config);
144}
145
146static void
147bgp_config_unset (struct bgp *bgp, int config)
148{
149 UNSET_FLAG (bgp->config, config);
150}
151
152static int
153bgp_config_check (struct bgp *bgp, int config)
154{
155 return CHECK_FLAG (bgp->config, config);
156}
157
158/* Set BGP router identifier. */
159int
160bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
161{
162 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000163 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000164
165 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
166 && IPV4_ADDR_SAME (&bgp->router_id, id))
167 return 0;
168
169 IPV4_ADDR_COPY (&bgp->router_id, id);
170 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
171
172 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000174 {
175 IPV4_ADDR_COPY (&peer->local_id, id);
176
177 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000178 {
179 peer->last_reset = PEER_DOWN_RID_CHANGE;
180 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
181 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
182 }
paul718e3742002-12-13 20:15:29 +0000183 }
184 return 0;
185}
186
paul718e3742002-12-13 20:15:29 +0000187/* BGP's cluster-id control. */
188int
189bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
190{
191 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000192 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000193
194 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
195 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
196 return 0;
197
198 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
199 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
200
201 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000202 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000203 {
204 if (peer_sort (peer) != BGP_PEER_IBGP)
205 continue;
206
207 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000208 {
209 peer->last_reset = PEER_DOWN_CLID_CHANGE;
210 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
211 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
212 }
paul718e3742002-12-13 20:15:29 +0000213 }
214 return 0;
215}
216
217int
218bgp_cluster_id_unset (struct bgp *bgp)
219{
220 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000221 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000222
223 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
224 return 0;
225
226 bgp->cluster_id.s_addr = 0;
227 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
228
229 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000230 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000231 {
232 if (peer_sort (peer) != BGP_PEER_IBGP)
233 continue;
234
235 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000236 {
237 peer->last_reset = PEER_DOWN_CLID_CHANGE;
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
239 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
240 }
paul718e3742002-12-13 20:15:29 +0000241 }
242 return 0;
243}
244
245/* BGP timer configuration. */
246int
247bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
248{
249 bgp->default_keepalive = (keepalive < holdtime / 3
250 ? keepalive : holdtime / 3);
251 bgp->default_holdtime = holdtime;
252
253 return 0;
254}
255
256int
257bgp_timers_unset (struct bgp *bgp)
258{
259 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
260 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
261
262 return 0;
263}
264
265/* BGP confederation configuration. */
266int
267bgp_confederation_id_set (struct bgp *bgp, as_t as)
268{
269 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000270 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000271 int already_confed;
272
273 if (as == 0)
274 return BGP_ERR_INVALID_AS;
275
276 /* Remember - were we doing confederation before? */
277 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
278 bgp->confed_id = as;
279 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
280
281 /* If we were doing confederation already, this is just an external
282 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
283 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000284 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000285 {
286 /* We're looking for peers who's AS is not local or part of our
287 confederation. */
288 if (already_confed)
289 {
290 if (peer_sort (peer) == BGP_PEER_EBGP)
291 {
292 peer->local_as = as;
293 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000294 {
295 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
296 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
297 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
298 }
299
paul718e3742002-12-13 20:15:29 +0000300 else
301 BGP_EVENT_ADD (peer, BGP_Stop);
302 }
303 }
304 else
305 {
306 /* Not doign confederation before, so reset every non-local
307 session */
308 if (peer_sort (peer) != BGP_PEER_IBGP)
309 {
310 /* Reset the local_as to be our EBGP one */
311 if (peer_sort (peer) == BGP_PEER_EBGP)
312 peer->local_as = as;
313 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000314 {
315 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
316 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
317 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
318 }
paul718e3742002-12-13 20:15:29 +0000319 else
320 BGP_EVENT_ADD (peer, BGP_Stop);
321 }
322 }
323 }
324 return 0;
325}
326
327int
328bgp_confederation_id_unset (struct bgp *bgp)
329{
330 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000331 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000332
333 bgp->confed_id = 0;
334 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
335
paul1eb8ef22005-04-07 07:30:20 +0000336 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000337 {
338 /* We're looking for peers who's AS is not local */
339 if (peer_sort (peer) != BGP_PEER_IBGP)
340 {
341 peer->local_as = bgp->as;
342 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000343 {
344 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
345 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
346 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
347 }
348
paul718e3742002-12-13 20:15:29 +0000349 else
350 BGP_EVENT_ADD (peer, BGP_Stop);
351 }
352 }
353 return 0;
354}
355
356/* Is an AS part of the confed or not? */
357int
358bgp_confederation_peers_check (struct bgp *bgp, as_t as)
359{
360 int i;
361
362 if (! bgp)
363 return 0;
364
365 for (i = 0; i < bgp->confed_peers_cnt; i++)
366 if (bgp->confed_peers[i] == as)
367 return 1;
368
369 return 0;
370}
371
372/* Add an AS to the confederation set. */
373int
374bgp_confederation_peers_add (struct bgp *bgp, as_t as)
375{
376 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000377 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000378
379 if (! bgp)
380 return BGP_ERR_INVALID_BGP;
381
382 if (bgp->as == as)
383 return BGP_ERR_INVALID_AS;
384
385 if (bgp_confederation_peers_check (bgp, as))
386 return -1;
387
388 if (bgp->confed_peers)
389 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
390 bgp->confed_peers,
391 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
392 else
393 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
394 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
395
396 bgp->confed_peers[bgp->confed_peers_cnt] = as;
397 bgp->confed_peers_cnt++;
398
399 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
400 {
paul1eb8ef22005-04-07 07:30:20 +0000401 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000402 {
403 if (peer->as == as)
404 {
405 peer->local_as = bgp->as;
406 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000407 {
408 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
409 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
410 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
411 }
paul718e3742002-12-13 20:15:29 +0000412 else
413 BGP_EVENT_ADD (peer, BGP_Stop);
414 }
415 }
416 }
417 return 0;
418}
419
420/* Delete an AS from the confederation set. */
421int
422bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
423{
424 int i;
425 int j;
426 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000427 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000428
429 if (! bgp)
430 return -1;
431
432 if (! bgp_confederation_peers_check (bgp, as))
433 return -1;
434
435 for (i = 0; i < bgp->confed_peers_cnt; i++)
436 if (bgp->confed_peers[i] == as)
437 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
438 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
439
440 bgp->confed_peers_cnt--;
441
442 if (bgp->confed_peers_cnt == 0)
443 {
444 if (bgp->confed_peers)
445 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
446 bgp->confed_peers = NULL;
447 }
448 else
449 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
450 bgp->confed_peers,
451 bgp->confed_peers_cnt * sizeof (as_t));
452
453 /* Now reset any peer who's remote AS has just been removed from the
454 CONFED */
455 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
456 {
paul1eb8ef22005-04-07 07:30:20 +0000457 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000458 {
459 if (peer->as == as)
460 {
461 peer->local_as = bgp->confed_id;
462 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000463 {
464 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
465 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
466 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
467 }
paul718e3742002-12-13 20:15:29 +0000468 else
469 BGP_EVENT_ADD (peer, BGP_Stop);
470 }
471 }
472 }
473
474 return 0;
475}
476
477/* Local preference configuration. */
478int
479bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
480{
481 if (! bgp)
482 return -1;
483
paul718e3742002-12-13 20:15:29 +0000484 bgp->default_local_pref = local_pref;
485
486 return 0;
487}
488
489int
490bgp_default_local_preference_unset (struct bgp *bgp)
491{
492 if (! bgp)
493 return -1;
494
paul718e3742002-12-13 20:15:29 +0000495 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
496
497 return 0;
498}
499
paulfee0f4c2004-09-13 05:12:46 +0000500/* If peer is RSERVER_CLIENT in at least one address family and is not member
501 of a peer_group for that family, return 1.
502 Used to check wether the peer is included in list bgp->rsclient. */
503int
504peer_rsclient_active (struct peer *peer)
505{
506 int i;
507 int j;
508
509 for (i=AFI_IP; i < AFI_MAX; i++)
510 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
511 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
512 && ! peer->af_group[i][j])
513 return 1;
514 return 0;
515}
516
pauleb821182004-05-01 08:44:08 +0000517/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000518static int
519peer_cmp (struct peer *p1, struct peer *p2)
520{
pauleb821182004-05-01 08:44:08 +0000521 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000522}
523
524int
525peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
526{
527 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
528}
529
530/* Reset all address family specific configuration. */
531static void
532peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
533{
534 int i;
535 struct bgp_filter *filter;
536 char orf_name[BUFSIZ];
537
538 filter = &peer->filter[afi][safi];
539
540 /* Clear neighbor filter and route-map */
541 for (i = FILTER_IN; i < FILTER_MAX; i++)
542 {
543 if (filter->dlist[i].name)
544 {
545 free (filter->dlist[i].name);
546 filter->dlist[i].name = NULL;
547 }
548 if (filter->plist[i].name)
549 {
550 free (filter->plist[i].name);
551 filter->plist[i].name = NULL;
552 }
553 if (filter->aslist[i].name)
554 {
555 free (filter->aslist[i].name);
556 filter->aslist[i].name = NULL;
557 }
paulfee0f4c2004-09-13 05:12:46 +0000558 }
559 for (i = RMAP_IN; i < RMAP_MAX; i++)
560 {
paul718e3742002-12-13 20:15:29 +0000561 if (filter->map[i].name)
562 {
563 free (filter->map[i].name);
564 filter->map[i].name = NULL;
565 }
566 }
567
568 /* Clear unsuppress map. */
569 if (filter->usmap.name)
570 free (filter->usmap.name);
571 filter->usmap.name = NULL;
572 filter->usmap.map = NULL;
573
574 /* Clear neighbor's all address family flags. */
575 peer->af_flags[afi][safi] = 0;
576
577 /* Clear neighbor's all address family sflags. */
578 peer->af_sflags[afi][safi] = 0;
579
580 /* Clear neighbor's all address family capabilities. */
581 peer->af_cap[afi][safi] = 0;
582
583 /* Clear ORF info */
584 peer->orf_plist[afi][safi] = NULL;
585 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
586 prefix_bgp_orf_remove_all (orf_name);
587
588 /* Set default neighbor send-community. */
589 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
590 {
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
592 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
593 }
594
595 /* Clear neighbor default_originate_rmap */
596 if (peer->default_rmap[afi][safi].name)
597 free (peer->default_rmap[afi][safi].name);
598 peer->default_rmap[afi][safi].name = NULL;
599 peer->default_rmap[afi][safi].map = NULL;
600
601 /* Clear neighbor maximum-prefix */
602 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000603 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000604}
605
606/* peer global config reset */
607void
608peer_global_config_reset (struct peer *peer)
609{
610 peer->weight = 0;
611 peer->change_local_as = 0;
612 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
613 if (peer->update_source)
614 {
615 sockunion_free (peer->update_source);
616 peer->update_source = NULL;
617 }
618 if (peer->update_if)
619 {
620 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
621 peer->update_if = NULL;
622 }
623
624 if (peer_sort (peer) == BGP_PEER_IBGP)
625 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
626 else
627 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
628
629 peer->flags = 0;
630 peer->config = 0;
631 peer->holdtime = 0;
632 peer->keepalive = 0;
633 peer->connect = 0;
634 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
635}
636
637/* Check peer's AS number and determin is this peer IBGP or EBGP */
638int
639peer_sort (struct peer *peer)
640{
641 struct bgp *bgp;
642
643 bgp = peer->bgp;
644
645 /* Peer-group */
646 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
647 {
648 if (peer->as)
649 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
650 else
651 {
652 struct peer *peer1;
653 peer1 = listnode_head (peer->group->peer);
654 if (peer1)
655 return (peer1->local_as == peer1->as
656 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
657 }
658 return BGP_PEER_INTERNAL;
659 }
660
661 /* Normal peer */
662 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
663 {
664 if (peer->local_as == 0)
665 return BGP_PEER_INTERNAL;
666
667 if (peer->local_as == peer->as)
668 {
669 if (peer->local_as == bgp->confed_id)
670 return BGP_PEER_EBGP;
671 else
672 return BGP_PEER_IBGP;
673 }
674
675 if (bgp_confederation_peers_check (bgp, peer->as))
676 return BGP_PEER_CONFED;
677
678 return BGP_PEER_EBGP;
679 }
680 else
681 {
682 return (peer->local_as == 0
683 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
684 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
685 }
686}
687
688/* Allocate new peer object. */
689static struct peer *
690peer_new ()
691{
692 afi_t afi;
693 safi_t safi;
694 struct peer *peer;
695 struct servent *sp;
696
697 /* Allocate new peer. */
698 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
699 memset (peer, 0, sizeof (struct peer));
700
701 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000702 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000703 peer->v_start = BGP_INIT_START_TIMER;
704 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
705 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
706 peer->status = Idle;
707 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000708 peer->weight = 0;
709
710 /* Set default flags. */
711 for (afi = AFI_IP; afi < AFI_MAX; afi++)
712 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
713 {
714 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
715 {
716 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
717 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
718 }
719 peer->orf_plist[afi][safi] = NULL;
720 }
721 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
722
723 /* Create buffers. */
724 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
725 peer->obuf = stream_fifo_new ();
726 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
727
728 bgp_sync_init (peer);
729
730 /* Get service port number. */
731 sp = getservbyname ("bgp", "tcp");
732 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
733
734 return peer;
735}
736
737/* Create new BGP peer. */
738struct peer *
739peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
740 as_t remote_as, afi_t afi, safi_t safi)
741{
742 int active;
743 struct peer *peer;
744 char buf[SU_ADDRSTRLEN];
745
746 peer = peer_new ();
747 peer->bgp = bgp;
748 peer->su = *su;
749 peer->local_as = local_as;
750 peer->as = remote_as;
751 peer->local_id = bgp->router_id;
752 peer->v_holdtime = bgp->default_holdtime;
753 peer->v_keepalive = bgp->default_keepalive;
754 if (peer_sort (peer) == BGP_PEER_IBGP)
755 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
756 else
757 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
758 listnode_add_sort (bgp->peer, peer);
759
760 active = peer_active (peer);
761
762 if (afi && safi)
763 peer->afc[afi][safi] = 1;
764
765 /* Last read time set */
766 peer->readtime = time (NULL);
767
paul848973c2003-08-13 00:32:49 +0000768 /* Last reset time set */
769 peer->resettime = time (NULL);
770
paul718e3742002-12-13 20:15:29 +0000771 /* Default TTL set. */
772 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
773
774 /* Make peer's address string. */
775 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000776 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000777
778 /* Set up peer's events and timers. */
779 if (! active && peer_active (peer))
780 bgp_timer_set (peer);
781
782 return peer;
783}
784
pauleb821182004-05-01 08:44:08 +0000785/* Make accept BGP peer. Called from bgp_accept (). */
786struct peer *
787peer_create_accept (struct bgp *bgp)
788{
789 struct peer *peer;
790
791 peer = peer_new ();
792 peer->bgp = bgp;
793 listnode_add_sort (bgp->peer, peer);
794
795 return peer;
796}
797
paul718e3742002-12-13 20:15:29 +0000798/* Change peer's AS number. */
799void
800peer_as_change (struct peer *peer, as_t as)
801{
802 int type;
803
804 /* Stop peer. */
805 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
806 {
807 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000808 {
809 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
810 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
811 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
812 }
paul718e3742002-12-13 20:15:29 +0000813 else
814 BGP_EVENT_ADD (peer, BGP_Stop);
815 }
816 type = peer_sort (peer);
817 peer->as = as;
818
paul848973c2003-08-13 00:32:49 +0000819 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
820 && ! bgp_confederation_peers_check (peer->bgp, as)
821 && peer->bgp->as != as)
822 peer->local_as = peer->bgp->confed_id;
823 else
824 peer->local_as = peer->bgp->as;
825
paul718e3742002-12-13 20:15:29 +0000826 /* Advertisement-interval reset */
827 if (peer_sort (peer) == BGP_PEER_IBGP)
828 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
829 else
830 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
831
832 /* TTL reset */
833 if (peer_sort (peer) == BGP_PEER_IBGP)
834 peer->ttl = 255;
835 else if (type == BGP_PEER_IBGP)
836 peer->ttl = 1;
837
838 /* reflector-client reset */
839 if (peer_sort (peer) != BGP_PEER_IBGP)
840 {
841 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
842 PEER_FLAG_REFLECTOR_CLIENT);
843 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
844 PEER_FLAG_REFLECTOR_CLIENT);
845 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
846 PEER_FLAG_REFLECTOR_CLIENT);
847 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
848 PEER_FLAG_REFLECTOR_CLIENT);
849 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
850 PEER_FLAG_REFLECTOR_CLIENT);
851 }
852
853 /* local-as reset */
854 if (peer_sort (peer) != BGP_PEER_EBGP)
855 {
856 peer->change_local_as = 0;
857 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
858 }
859}
860
861/* If peer does not exist, create new one. If peer already exists,
862 set AS number to the peer. */
863int
864peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
865 afi_t afi, safi_t safi)
866{
867 struct peer *peer;
868 as_t local_as;
869
870 peer = peer_lookup (bgp, su);
871
872 if (peer)
873 {
874 /* When this peer is a member of peer-group. */
875 if (peer->group)
876 {
877 if (peer->group->conf->as)
878 {
879 /* Return peer group's AS number. */
880 *as = peer->group->conf->as;
881 return BGP_ERR_PEER_GROUP_MEMBER;
882 }
883 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
884 {
885 if (bgp->as != *as)
886 {
887 *as = peer->as;
888 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
889 }
890 }
891 else
892 {
893 if (bgp->as == *as)
894 {
895 *as = peer->as;
896 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
897 }
898 }
899 }
900
901 /* Existing peer's AS number change. */
902 if (peer->as != *as)
903 peer_as_change (peer, *as);
904 }
905 else
906 {
907
908 /* If the peer is not part of our confederation, and its not an
909 iBGP peer then spoof the source AS */
910 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
911 && ! bgp_confederation_peers_check (bgp, *as)
912 && bgp->as != *as)
913 local_as = bgp->confed_id;
914 else
915 local_as = bgp->as;
916
917 /* If this is IPv4 unicast configuration and "no bgp default
918 ipv4-unicast" is specified. */
919
920 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
921 && afi == AFI_IP && safi == SAFI_UNICAST)
922 peer = peer_create (su, bgp, local_as, *as, 0, 0);
923 else
924 peer = peer_create (su, bgp, local_as, *as, afi, safi);
925 }
926
927 return 0;
928}
929
930/* Activate the peer or peer group for specified AFI and SAFI. */
931int
932peer_activate (struct peer *peer, afi_t afi, safi_t safi)
933{
934 int active;
935
936 if (peer->afc[afi][safi])
937 return 0;
938
939 /* Activate the address family configuration. */
940 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
941 peer->afc[afi][safi] = 1;
942 else
943 {
944 active = peer_active (peer);
945
946 peer->afc[afi][safi] = 1;
947
948 if (! active && peer_active (peer))
949 bgp_timer_set (peer);
950 else
951 {
952 if (peer->status == Established)
953 {
954 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
955 {
956 peer->afc_adv[afi][safi] = 1;
957 bgp_capability_send (peer, afi, safi,
958 CAPABILITY_CODE_MP,
959 CAPABILITY_ACTION_SET);
960 if (peer->afc_recv[afi][safi])
961 {
962 peer->afc_nego[afi][safi] = 1;
963 bgp_announce_route (peer, afi, safi);
964 }
965 }
966 else
hassoe0701b72004-05-20 09:19:34 +0000967 {
968 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
969 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
970 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
971 }
paul718e3742002-12-13 20:15:29 +0000972 }
973 }
974 }
975 return 0;
976}
977
978int
979peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
980{
981 struct peer_group *group;
982 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +0000983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000984
985 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
986 {
987 group = peer->group;
988
paul1eb8ef22005-04-07 07:30:20 +0000989 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +0000990 {
991 if (peer1->af_group[afi][safi])
992 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
993 }
994 }
995 else
996 {
997 if (peer->af_group[afi][safi])
998 return BGP_ERR_PEER_BELONGS_TO_GROUP;
999 }
1000
1001 if (! peer->afc[afi][safi])
1002 return 0;
1003
1004 /* De-activate the address family configuration. */
1005 peer->afc[afi][safi] = 0;
1006 peer_af_flag_reset (peer, afi, safi);
1007
1008 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1009 {
1010 if (peer->status == Established)
1011 {
1012 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1013 {
1014 peer->afc_adv[afi][safi] = 0;
1015 peer->afc_nego[afi][safi] = 0;
1016
1017 if (peer_active_nego (peer))
1018 {
1019 bgp_capability_send (peer, afi, safi,
1020 CAPABILITY_CODE_MP,
1021 CAPABILITY_ACTION_UNSET);
1022 bgp_clear_route (peer, afi, safi);
1023 peer->pcount[afi][safi] = 0;
1024 }
1025 else
hassoe0701b72004-05-20 09:19:34 +00001026 {
1027 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1028 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1029 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1030 }
paul718e3742002-12-13 20:15:29 +00001031 }
1032 else
hassoe0701b72004-05-20 09:19:34 +00001033 {
1034 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1035 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1036 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1037 }
paul718e3742002-12-13 20:15:29 +00001038 }
1039 }
1040 return 0;
1041}
1042
hasso93406d82005-02-02 14:40:33 +00001043void
1044peer_nsf_stop (struct peer *peer)
1045{
1046 afi_t afi;
1047 safi_t safi;
1048
1049 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1050 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1051
1052 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1053 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1054 peer->nsf[afi][safi] = 0;
1055
1056 if (peer->t_gr_restart)
1057 {
1058 BGP_TIMER_OFF (peer->t_gr_restart);
1059 if (BGP_DEBUG (events, EVENTS))
1060 zlog_debug ("%s graceful restart timer stopped", peer->host);
1061 }
1062 if (peer->t_gr_stale)
1063 {
1064 BGP_TIMER_OFF (peer->t_gr_stale);
1065 if (BGP_DEBUG (events, EVENTS))
1066 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1067 }
1068 bgp_clear_route_all (peer);
1069}
1070
paul718e3742002-12-13 20:15:29 +00001071/* Delete peer from confguration. */
1072int
1073peer_delete (struct peer *peer)
1074{
1075 int i;
1076 afi_t afi;
1077 safi_t safi;
1078 struct bgp *bgp;
1079 struct bgp_filter *filter;
1080
1081 bgp = peer->bgp;
1082
hasso93406d82005-02-02 14:40:33 +00001083 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1084 peer_nsf_stop (peer);
1085
paul718e3742002-12-13 20:15:29 +00001086 /* If this peer belongs to peer group. Clearn up the
1087 relationship. */
1088 if (peer->group)
1089 {
1090 listnode_delete (peer->group->peer, peer);
1091 peer->group = NULL;
1092 }
1093
1094 /* Withdraw all information from routing table. We can not use
1095 BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1096 executed after peer structure is deleted. */
hassoe0701b72004-05-20 09:19:34 +00001097 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001098 bgp_stop (peer);
1099 bgp_fsm_change_status (peer, Idle);
1100
1101 /* Stop all timers. */
1102 BGP_TIMER_OFF (peer->t_start);
1103 BGP_TIMER_OFF (peer->t_connect);
1104 BGP_TIMER_OFF (peer->t_holdtime);
1105 BGP_TIMER_OFF (peer->t_keepalive);
1106 BGP_TIMER_OFF (peer->t_asorig);
1107 BGP_TIMER_OFF (peer->t_routeadv);
hasso0a486e52005-02-01 20:57:17 +00001108 BGP_TIMER_OFF (peer->t_pmax_restart);
hasso93406d82005-02-02 14:40:33 +00001109 BGP_TIMER_OFF (peer->t_gr_restart);
1110 BGP_TIMER_OFF (peer->t_gr_stale);
paul718e3742002-12-13 20:15:29 +00001111
1112 /* Delete from all peer list. */
1113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001114 {
paul718e3742002-12-13 20:15:29 +00001115 listnode_delete (bgp->peer, peer);
paulfee0f4c2004-09-13 05:12:46 +00001116 if (peer_rsclient_active (peer))
1117 listnode_delete (bgp->rsclient, peer);
1118 }
1119
1120 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1121 member of a peer_group. */
1122 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1123 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1124 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1125 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001126
1127 /* Buffer. */
1128 if (peer->ibuf)
1129 stream_free (peer->ibuf);
1130
1131 if (peer->obuf)
1132 stream_fifo_free (peer->obuf);
1133
1134 if (peer->work)
1135 stream_free (peer->work);
1136
1137 /* Free allocated host character. */
1138 if (peer->host)
paule83e2082005-05-19 02:12:25 +00001139 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
paul718e3742002-12-13 20:15:29 +00001140
1141 /* Local and remote addresses. */
1142 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001143 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001144 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001145 sockunion_free (peer->su_remote);
paul718e3742002-12-13 20:15:29 +00001146
1147 /* Peer description string. */
1148 if (peer->desc)
paule83e2082005-05-19 02:12:25 +00001149 XFREE (MTYPE_PEER_DESC, peer->desc);
paul718e3742002-12-13 20:15:29 +00001150
1151 bgp_sync_delete (peer);
1152
1153 /* Free filter related memory. */
1154 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1155 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1156 {
1157 filter = &peer->filter[afi][safi];
1158
1159 for (i = FILTER_IN; i < FILTER_MAX; i++)
1160 {
1161 if (filter->dlist[i].name)
1162 free (filter->dlist[i].name);
1163 if (filter->plist[i].name)
1164 free (filter->plist[i].name);
1165 if (filter->aslist[i].name)
1166 free (filter->aslist[i].name);
paulfee0f4c2004-09-13 05:12:46 +00001167 }
1168 for (i = RMAP_IN; i < RMAP_MAX; i++)
1169 {
paul718e3742002-12-13 20:15:29 +00001170 if (filter->map[i].name)
1171 free (filter->map[i].name);
1172 }
1173
1174 if (filter->usmap.name)
1175 free (filter->usmap.name);
1176
1177 if (peer->default_rmap[afi][safi].name)
1178 free (peer->default_rmap[afi][safi].name);
1179 }
1180
1181 /* Update source configuration. */
1182 if (peer->update_source)
1183 {
1184 sockunion_free (peer->update_source);
1185 peer->update_source = NULL;
1186 }
1187 if (peer->update_if)
1188 {
1189 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1190 peer->update_if = NULL;
1191 }
1192
1193 /* Free peer structure. */
1194 XFREE (MTYPE_BGP_PEER, peer);
1195
1196 return 0;
1197}
1198
1199int
1200peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1201{
1202 return strcmp (g1->name, g2->name);
1203}
1204
1205/* If peer is configured at least one address family return 1. */
1206int
1207peer_group_active (struct peer *peer)
1208{
1209 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1210 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1211 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1212 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1213 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1214 return 1;
1215 return 0;
1216}
1217
1218/* Peer group cofiguration. */
1219static struct peer_group *
1220peer_group_new ()
1221{
1222 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1223 sizeof (struct peer_group));
1224}
1225
1226void
1227peer_group_free (struct peer_group *group)
1228{
1229 XFREE (MTYPE_PEER_GROUP, group);
1230}
1231
1232struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001233peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001234{
1235 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001236 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001237
paul1eb8ef22005-04-07 07:30:20 +00001238 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001239 {
1240 if (strcmp (group->name, name) == 0)
1241 return group;
1242 }
1243 return NULL;
1244}
1245
1246struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001247peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001248{
1249 struct peer_group *group;
1250
1251 group = peer_group_lookup (bgp, name);
1252 if (group)
1253 return group;
1254
1255 group = peer_group_new ();
1256 group->bgp = bgp;
1257 group->name = strdup (name);
1258 group->peer = list_new ();
1259 group->conf = peer_new ();
1260 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1261 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1262 group->conf->host = strdup (name);
1263 group->conf->bgp = bgp;
1264 group->conf->group = group;
1265 group->conf->as = 0;
1266 group->conf->ttl = 1;
1267 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1268 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1269 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1270 group->conf->keepalive = 0;
1271 group->conf->holdtime = 0;
1272 group->conf->connect = 0;
1273 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1274 listnode_add_sort (bgp->group, group);
1275
1276 return 0;
1277}
1278
1279void
1280peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1281 afi_t afi, safi_t safi)
1282{
1283 int in = FILTER_IN;
1284 int out = FILTER_OUT;
1285 struct peer *conf;
1286 struct bgp_filter *pfilter;
1287 struct bgp_filter *gfilter;
1288
1289 conf = group->conf;
1290 pfilter = &peer->filter[afi][safi];
1291 gfilter = &conf->filter[afi][safi];
1292
1293 /* remote-as */
1294 if (conf->as)
1295 peer->as = conf->as;
1296
1297 /* remote-as */
1298 if (conf->change_local_as)
1299 peer->change_local_as = conf->change_local_as;
1300
1301 /* TTL */
1302 peer->ttl = conf->ttl;
1303
1304 /* Weight */
1305 peer->weight = conf->weight;
1306
1307 /* peer flags apply */
1308 peer->flags = conf->flags;
1309 /* peer af_flags apply */
1310 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1311 /* peer config apply */
1312 peer->config = conf->config;
1313
1314 /* peer timers apply */
1315 peer->holdtime = conf->holdtime;
1316 peer->keepalive = conf->keepalive;
1317 peer->connect = conf->connect;
1318 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1319 peer->v_connect = conf->connect;
1320 else
1321 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1322
1323 /* advertisement-interval reset */
1324 if (peer_sort (peer) == BGP_PEER_IBGP)
1325 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1326 else
1327 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1328
1329 /* maximum-prefix */
1330 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001331 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001332 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001333
1334 /* allowas-in */
1335 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1336
paulfee0f4c2004-09-13 05:12:46 +00001337 /* route-server-client */
1338 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1339 {
1340 /* Make peer's RIB point to group's RIB. */
1341 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1342
1343 /* Import policy. */
1344 if (pfilter->map[RMAP_IMPORT].name)
1345 free (pfilter->map[RMAP_IMPORT].name);
1346 if (gfilter->map[RMAP_IMPORT].name)
1347 {
1348 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1349 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1350 }
1351 else
1352 {
1353 pfilter->map[RMAP_IMPORT].name = NULL;
1354 pfilter->map[RMAP_IMPORT].map = NULL;
1355 }
1356
1357 /* Export policy. */
1358 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1359 {
1360 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1361 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1362 }
1363 }
1364
paul718e3742002-12-13 20:15:29 +00001365 /* default-originate route-map */
1366 if (conf->default_rmap[afi][safi].name)
1367 {
1368 if (peer->default_rmap[afi][safi].name)
1369 free (peer->default_rmap[afi][safi].name);
1370 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1371 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1372 }
1373
1374 /* update-source apply */
1375 if (conf->update_source)
1376 {
1377 if (peer->update_source)
1378 sockunion_free (peer->update_source);
1379 if (peer->update_if)
1380 {
1381 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1382 peer->update_if = NULL;
1383 }
1384 peer->update_source = sockunion_dup (conf->update_source);
1385 }
1386 else if (conf->update_if)
1387 {
1388 if (peer->update_if)
1389 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1390 if (peer->update_source)
1391 {
1392 sockunion_free (peer->update_source);
1393 peer->update_source = NULL;
1394 }
1395 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1396 }
1397
1398 /* inbound filter apply */
1399 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1400 {
1401 if (pfilter->dlist[in].name)
1402 free (pfilter->dlist[in].name);
1403 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1404 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1405 }
1406 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1407 {
1408 if (pfilter->plist[in].name)
1409 free (pfilter->plist[in].name);
1410 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1411 pfilter->plist[in].plist = gfilter->plist[in].plist;
1412 }
1413 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1414 {
1415 if (pfilter->aslist[in].name)
1416 free (pfilter->aslist[in].name);
1417 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1418 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1419 }
paulfee0f4c2004-09-13 05:12:46 +00001420 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001421 {
paulfee0f4c2004-09-13 05:12:46 +00001422 if (pfilter->map[RMAP_IN].name)
1423 free (pfilter->map[RMAP_IN].name);
1424 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1425 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001426 }
1427
1428 /* outbound filter apply */
1429 if (gfilter->dlist[out].name)
1430 {
1431 if (pfilter->dlist[out].name)
1432 free (pfilter->dlist[out].name);
1433 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1434 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1435 }
1436 else
1437 {
1438 if (pfilter->dlist[out].name)
1439 free (pfilter->dlist[out].name);
1440 pfilter->dlist[out].name = NULL;
1441 pfilter->dlist[out].alist = NULL;
1442 }
1443 if (gfilter->plist[out].name)
1444 {
1445 if (pfilter->plist[out].name)
1446 free (pfilter->plist[out].name);
1447 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1448 pfilter->plist[out].plist = gfilter->plist[out].plist;
1449 }
1450 else
1451 {
1452 if (pfilter->plist[out].name)
1453 free (pfilter->plist[out].name);
1454 pfilter->plist[out].name = NULL;
1455 pfilter->plist[out].plist = NULL;
1456 }
1457 if (gfilter->aslist[out].name)
1458 {
1459 if (pfilter->aslist[out].name)
1460 free (pfilter->aslist[out].name);
1461 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1462 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1463 }
1464 else
1465 {
1466 if (pfilter->aslist[out].name)
1467 free (pfilter->aslist[out].name);
1468 pfilter->aslist[out].name = NULL;
1469 pfilter->aslist[out].aslist = NULL;
1470 }
paulfee0f4c2004-09-13 05:12:46 +00001471 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001472 {
paulfee0f4c2004-09-13 05:12:46 +00001473 if (pfilter->map[RMAP_OUT].name)
1474 free (pfilter->map[RMAP_OUT].name);
1475 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1476 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001477 }
1478 else
1479 {
paulfee0f4c2004-09-13 05:12:46 +00001480 if (pfilter->map[RMAP_OUT].name)
1481 free (pfilter->map[RMAP_OUT].name);
1482 pfilter->map[RMAP_OUT].name = NULL;
1483 pfilter->map[RMAP_OUT].map = NULL;
1484 }
1485
1486 /* RS-client's import/export route-maps. */
1487 if (gfilter->map[RMAP_IMPORT].name)
1488 {
1489 if (pfilter->map[RMAP_IMPORT].name)
1490 free (pfilter->map[RMAP_IMPORT].name);
1491 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1492 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1493 }
1494 else
1495 {
1496 if (pfilter->map[RMAP_IMPORT].name)
1497 free (pfilter->map[RMAP_IMPORT].name);
1498 pfilter->map[RMAP_IMPORT].name = NULL;
1499 pfilter->map[RMAP_IMPORT].map = NULL;
1500 }
1501 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1502 {
1503 if (pfilter->map[RMAP_EXPORT].name)
1504 free (pfilter->map[RMAP_EXPORT].name);
1505 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1506 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001507 }
1508
1509 if (gfilter->usmap.name)
1510 {
1511 if (pfilter->usmap.name)
1512 free (pfilter->usmap.name);
1513 pfilter->usmap.name = strdup (gfilter->usmap.name);
1514 pfilter->usmap.map = gfilter->usmap.map;
1515 }
1516 else
1517 {
1518 if (pfilter->usmap.name)
1519 free (pfilter->usmap.name);
1520 pfilter->usmap.name = NULL;
1521 pfilter->usmap.map = NULL;
1522 }
1523}
1524
1525/* Peer group's remote AS configuration. */
1526int
paulfd79ac92004-10-13 05:06:08 +00001527peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001528{
1529 struct peer_group *group;
1530 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001531 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001532
1533 group = peer_group_lookup (bgp, group_name);
1534 if (! group)
1535 return -1;
1536
1537 if (group->conf->as == *as)
1538 return 0;
1539
1540 /* When we setup peer-group AS number all peer group member's AS
1541 number must be updated to same number. */
1542 peer_as_change (group->conf, *as);
1543
paul1eb8ef22005-04-07 07:30:20 +00001544 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001545 {
1546 if (peer->as != *as)
1547 peer_as_change (peer, *as);
1548 }
1549
1550 return 0;
1551}
1552
1553int
1554peer_group_delete (struct peer_group *group)
1555{
1556 struct bgp *bgp;
1557 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001558 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001559
1560 bgp = group->bgp;
1561
paul1eb8ef22005-04-07 07:30:20 +00001562 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001563 {
1564 peer->group = NULL;
1565 peer_delete (peer);
1566 }
1567 list_delete (group->peer);
1568
1569 free (group->name);
1570 group->name = NULL;
1571
1572 group->conf->group = NULL;
1573 peer_delete (group->conf);
1574
1575 /* Delete from all peer_group list. */
1576 listnode_delete (bgp->group, group);
1577
1578 peer_group_free (group);
1579
1580 return 0;
1581}
1582
1583int
1584peer_group_remote_as_delete (struct peer_group *group)
1585{
1586 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001587 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001588
1589 if (! group->conf->as)
1590 return 0;
1591
paul1eb8ef22005-04-07 07:30:20 +00001592 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001593 {
1594 peer->group = NULL;
1595 peer_delete (peer);
1596 }
1597 list_delete_all_node (group->peer);
1598
1599 group->conf->as = 0;
1600
1601 return 0;
1602}
1603
1604/* Bind specified peer to peer group. */
1605int
1606peer_group_bind (struct bgp *bgp, union sockunion *su,
1607 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1608{
1609 struct peer *peer;
1610 int first_member = 0;
1611
1612 /* Check peer group's address family. */
1613 if (! group->conf->afc[afi][safi])
1614 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1615
1616 /* Lookup the peer. */
1617 peer = peer_lookup (bgp, su);
1618
1619 /* Create a new peer. */
1620 if (! peer)
1621 {
1622 if (! group->conf->as)
1623 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1624
1625 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1626 peer->group = group;
1627 peer->af_group[afi][safi] = 1;
1628 listnode_add (group->peer, peer);
1629 peer_group2peer_config_copy (group, peer, afi, safi);
1630
1631 return 0;
1632 }
1633
1634 /* When the peer already belongs to peer group, check the consistency. */
1635 if (peer->af_group[afi][safi])
1636 {
1637 if (strcmp (peer->group->name, group->name) != 0)
1638 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1639
1640 return 0;
1641 }
1642
1643 /* Check current peer group configuration. */
1644 if (peer_group_active (peer)
1645 && strcmp (peer->group->name, group->name) != 0)
1646 return BGP_ERR_PEER_GROUP_MISMATCH;
1647
1648 if (! group->conf->as)
1649 {
1650 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1651 && peer_sort (group->conf) != peer_sort (peer))
1652 {
1653 if (as)
1654 *as = peer->as;
1655 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1656 }
1657
1658 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1659 first_member = 1;
1660 }
1661
1662 peer->af_group[afi][safi] = 1;
1663 peer->afc[afi][safi] = 1;
1664 if (! peer->group)
1665 {
1666 peer->group = group;
1667 listnode_add (group->peer, peer);
1668 }
1669
1670 if (first_member)
1671 {
1672 /* Advertisement-interval reset */
1673 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1674 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1675 else
1676 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1677
1678 /* ebgp-multihop reset */
1679 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1680 group->conf->ttl = 255;
1681
1682 /* local-as reset */
1683 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1684 {
1685 group->conf->change_local_as = 0;
1686 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1687 }
1688 }
paulfee0f4c2004-09-13 05:12:46 +00001689
1690 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1691 {
1692 /* If it's not configured as RSERVER_CLIENT in any other address
1693 family, without being member of a peer_group, remove it from
1694 list bgp->rsclient.*/
1695 if (! peer_rsclient_active (peer))
1696 listnode_delete (bgp->rsclient, peer);
1697
1698 bgp_table_finish (peer->rib[afi][safi]);
1699
1700 /* Import policy. */
1701 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1702 {
1703 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1704 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1705 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1706 }
1707
1708 /* Export policy. */
1709 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1710 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1711 {
1712 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1713 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1714 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1715 }
1716 }
1717
paul718e3742002-12-13 20:15:29 +00001718 peer_group2peer_config_copy (group, peer, afi, safi);
1719
1720 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001721 {
1722 peer->last_reset = PEER_DOWN_RMAP_BIND;
1723 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1724 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1725 }
paul718e3742002-12-13 20:15:29 +00001726 else
1727 BGP_EVENT_ADD (peer, BGP_Stop);
1728
1729 return 0;
1730}
1731
1732int
1733peer_group_unbind (struct bgp *bgp, struct peer *peer,
1734 struct peer_group *group, afi_t afi, safi_t safi)
1735{
1736 if (! peer->af_group[afi][safi])
1737 return 0;
1738
1739 if (group != peer->group)
1740 return BGP_ERR_PEER_GROUP_MISMATCH;
1741
1742 peer->af_group[afi][safi] = 0;
1743 peer->afc[afi][safi] = 0;
1744 peer_af_flag_reset (peer, afi, safi);
1745
paulfee0f4c2004-09-13 05:12:46 +00001746 if (peer->rib[afi][safi])
1747 peer->rib[afi][safi] = NULL;
1748
paul718e3742002-12-13 20:15:29 +00001749 if (! peer_group_active (peer))
1750 {
1751 listnode_delete (group->peer, peer);
1752 peer->group = NULL;
1753 if (group->conf->as)
1754 {
1755 peer_delete (peer);
1756 return 0;
1757 }
1758 peer_global_config_reset (peer);
1759 }
1760
1761 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001762 {
1763 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1764 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1765 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1766 }
paul718e3742002-12-13 20:15:29 +00001767 else
1768 BGP_EVENT_ADD (peer, BGP_Stop);
1769
1770 return 0;
1771}
1772
1773/* BGP instance creation by `router bgp' commands. */
1774struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001775bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001776{
1777 struct bgp *bgp;
1778 afi_t afi;
1779 safi_t safi;
1780
1781 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1782
1783 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001784 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001785
1786 bgp->peer = list_new ();
1787 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1788
1789 bgp->group = list_new ();
1790 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1791
paulfee0f4c2004-09-13 05:12:46 +00001792 bgp->rsclient = list_new ();
1793 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1794
paul718e3742002-12-13 20:15:29 +00001795 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1796 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1797 {
1798 bgp->route[afi][safi] = bgp_table_init ();
1799 bgp->aggregate[afi][safi] = bgp_table_init ();
1800 bgp->rib[afi][safi] = bgp_table_init ();
1801 }
1802
1803 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1804 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1805 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001806 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1807 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001808
1809 bgp->as = *as;
1810
1811 if (name)
1812 bgp->name = strdup (name);
1813
1814 return bgp;
1815}
1816
1817/* Return first entry of BGP. */
1818struct bgp *
1819bgp_get_default ()
1820{
1821 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001822 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001823 return NULL;
1824}
1825
1826/* Lookup BGP entry. */
1827struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001828bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001829{
1830 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001831 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001832
paul1eb8ef22005-04-07 07:30:20 +00001833 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001834 if (bgp->as == as
1835 && ((bgp->name == NULL && name == NULL)
1836 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1837 return bgp;
1838 return NULL;
1839}
1840
1841/* Lookup BGP structure by view name. */
1842struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001843bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001844{
1845 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001846 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001847
paul1eb8ef22005-04-07 07:30:20 +00001848 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001849 if ((bgp->name == NULL && name == NULL)
1850 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1851 return bgp;
1852 return NULL;
1853}
1854
1855/* Called from VTY commands. */
1856int
paulfd79ac92004-10-13 05:06:08 +00001857bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001858{
1859 struct bgp *bgp;
1860
1861 /* Multiple instance check. */
1862 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1863 {
1864 if (name)
1865 bgp = bgp_lookup_by_name (name);
1866 else
1867 bgp = bgp_get_default ();
1868
1869 /* Already exists. */
1870 if (bgp)
1871 {
1872 if (bgp->as != *as)
1873 {
1874 *as = bgp->as;
1875 return BGP_ERR_INSTANCE_MISMATCH;
1876 }
1877 *bgp_val = bgp;
1878 return 0;
1879 }
1880 }
1881 else
1882 {
1883 /* BGP instance name can not be specified for single instance. */
1884 if (name)
1885 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1886
1887 /* Get default BGP structure if exists. */
1888 bgp = bgp_get_default ();
1889
1890 if (bgp)
1891 {
1892 if (bgp->as != *as)
1893 {
1894 *as = bgp->as;
1895 return BGP_ERR_AS_MISMATCH;
1896 }
1897 *bgp_val = bgp;
1898 return 0;
1899 }
1900 }
1901
1902 bgp = bgp_create (as, name);
1903 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001904 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001905 *bgp_val = bgp;
1906
1907 return 0;
1908}
1909
1910/* Delete BGP instance. */
1911int
1912bgp_delete (struct bgp *bgp)
1913{
1914 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00001915 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001916 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001917 struct listnode *next;
1918 afi_t afi;
1919 safi_t safi;
1920 int i;
1921
1922 /* Delete static route. */
1923 bgp_static_delete (bgp);
1924
1925 /* Unset redistribution. */
1926 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1927 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1928 if (i != ZEBRA_ROUTE_BGP)
1929 bgp_redistribute_unset (bgp, afi, i);
1930
hassob6b7cff2005-05-26 08:29:07 +00001931 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
1932 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00001933 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00001934
paul1eb8ef22005-04-07 07:30:20 +00001935 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
1936 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00001937 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00001938
hasso54a6ed32005-05-26 22:12:33 +00001939 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
1940 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00001941 list_delete (bgp->rsclient);
1942
paul718e3742002-12-13 20:15:29 +00001943 listnode_delete (bm->bgp, bgp);
1944
1945 if (bgp->name)
1946 free (bgp->name);
1947
1948 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1949 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1950 {
1951 if (bgp->route[afi][safi])
1952 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1953 if (bgp->aggregate[afi][safi])
1954 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1955 if (bgp->rib[afi][safi])
1956 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1957 }
1958 XFREE (MTYPE_BGP, bgp);
1959
1960 return 0;
1961}
1962
1963struct peer *
1964peer_lookup (struct bgp *bgp, union sockunion *su)
1965{
1966 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001967 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001968
1969 if (! bgp)
1970 bgp = bgp_get_default ();
1971
1972 if (! bgp)
1973 return NULL;
1974
paul1eb8ef22005-04-07 07:30:20 +00001975 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001976 {
pauleb821182004-05-01 08:44:08 +00001977 if (sockunion_same (&peer->su, su)
1978 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1979 return peer;
paul718e3742002-12-13 20:15:29 +00001980 }
1981 return NULL;
1982}
1983
1984struct peer *
1985peer_lookup_with_open (union sockunion *su, as_t remote_as,
1986 struct in_addr *remote_id, int *as)
1987{
1988 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001989 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001990 struct bgp *bgp;
1991
1992 bgp = bgp_get_default ();
1993 if (! bgp)
1994 return NULL;
1995
paul1eb8ef22005-04-07 07:30:20 +00001996 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001997 {
pauleb821182004-05-01 08:44:08 +00001998 if (sockunion_same (&peer->su, su)
1999 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2000 {
2001 if (peer->as == remote_as
2002 && peer->remote_id.s_addr == remote_id->s_addr)
2003 return peer;
2004 if (peer->as == remote_as)
2005 *as = 1;
2006 }
paul718e3742002-12-13 20:15:29 +00002007 }
paul1eb8ef22005-04-07 07:30:20 +00002008 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002009 {
pauleb821182004-05-01 08:44:08 +00002010 if (sockunion_same (&peer->su, su)
2011 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2012 {
2013 if (peer->as == remote_as
2014 && peer->remote_id.s_addr == 0)
2015 return peer;
2016 if (peer->as == remote_as)
2017 *as = 1;
2018 }
paul718e3742002-12-13 20:15:29 +00002019 }
2020 return NULL;
2021}
2022
2023/* If peer is configured at least one address family return 1. */
2024int
2025peer_active (struct peer *peer)
2026{
2027 if (peer->afc[AFI_IP][SAFI_UNICAST]
2028 || peer->afc[AFI_IP][SAFI_MULTICAST]
2029 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2030 || peer->afc[AFI_IP6][SAFI_UNICAST]
2031 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2032 return 1;
2033 return 0;
2034}
2035
2036/* If peer is negotiated at least one address family return 1. */
2037int
2038peer_active_nego (struct peer *peer)
2039{
2040 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2041 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2042 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2043 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2044 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2045 return 1;
2046 return 0;
2047}
2048
2049/* peer_flag_change_type. */
2050enum peer_change_type
2051{
2052 peer_change_none,
2053 peer_change_reset,
2054 peer_change_reset_in,
2055 peer_change_reset_out,
2056};
2057
2058void
2059peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2060 enum peer_change_type type)
2061{
2062 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2063 return;
2064
2065 if (type == peer_change_reset)
2066 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2067 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2068 else if (type == peer_change_reset_in)
2069 {
2070 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2071 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2072 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2073 else
2074 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2075 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2076 }
2077 else if (type == peer_change_reset_out)
2078 bgp_announce_route (peer, afi, safi);
2079}
2080
2081struct peer_flag_action
2082{
2083 /* Peer's flag. */
2084 u_int32_t flag;
2085
2086 /* This flag can be set for peer-group member. */
2087 u_char not_for_member;
2088
2089 /* Action when the flag is changed. */
2090 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002091
2092 /* Peer down cause */
2093 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002094};
2095
2096struct peer_flag_action peer_flag_action_list[] =
2097 {
2098 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2099 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2100 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2101 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2102 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002103 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002104 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002105 { 0, 0, 0 }
2106 };
2107
2108struct peer_flag_action peer_af_flag_action_list[] =
2109 {
2110 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2111 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2112 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2113 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2114 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2115 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2116 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2117 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2118 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2119 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2120 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2121 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2122 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002123 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002124 { 0, 0, 0 }
2125 };
2126
2127/* Proper action set. */
2128int
2129peer_flag_action_set (struct peer_flag_action *action_list, int size,
2130 struct peer_flag_action *action, u_int32_t flag)
2131{
2132 int i;
2133 int found = 0;
2134 int reset_in = 0;
2135 int reset_out = 0;
2136 struct peer_flag_action *match = NULL;
2137
2138 /* Check peer's frag action. */
2139 for (i = 0; i < size; i++)
2140 {
2141 match = &action_list[i];
2142
2143 if (match->flag == 0)
2144 break;
2145
2146 if (match->flag & flag)
2147 {
2148 found = 1;
2149
2150 if (match->type == peer_change_reset_in)
2151 reset_in = 1;
2152 if (match->type == peer_change_reset_out)
2153 reset_out = 1;
2154 if (match->type == peer_change_reset)
2155 {
2156 reset_in = 1;
2157 reset_out = 1;
2158 }
2159 if (match->not_for_member)
2160 action->not_for_member = 1;
2161 }
2162 }
2163
2164 /* Set peer clear type. */
2165 if (reset_in && reset_out)
2166 action->type = peer_change_reset;
2167 else if (reset_in)
2168 action->type = peer_change_reset_in;
2169 else if (reset_out)
2170 action->type = peer_change_reset_out;
2171 else
2172 action->type = peer_change_none;
2173
2174 return found;
2175}
2176
2177void
2178peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2179{
2180 if (flag == PEER_FLAG_SHUTDOWN)
2181 {
2182 if (CHECK_FLAG (peer->flags, flag))
2183 {
hasso93406d82005-02-02 14:40:33 +00002184 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2185 peer_nsf_stop (peer);
2186
hasso0a486e52005-02-01 20:57:17 +00002187 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2188 if (peer->t_pmax_restart)
2189 {
2190 BGP_TIMER_OFF (peer->t_pmax_restart);
2191 if (BGP_DEBUG (events, EVENTS))
2192 zlog_debug ("%s Maximum-prefix restart timer canceled",
2193 peer->host);
2194 }
2195
hasso93406d82005-02-02 14:40:33 +00002196 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2197 peer_nsf_stop (peer);
2198
paul718e3742002-12-13 20:15:29 +00002199 if (peer->status == Established)
2200 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2201 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2202 else
2203 BGP_EVENT_ADD (peer, BGP_Stop);
2204 }
2205 else
2206 {
2207 peer->v_start = BGP_INIT_START_TIMER;
2208 BGP_EVENT_ADD (peer, BGP_Stop);
2209 }
2210 }
2211 else if (peer->status == Established)
2212 {
hassoc9502432005-02-01 22:01:48 +00002213 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2214 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2215 else if (flag == PEER_FLAG_PASSIVE)
2216 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002217 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002218 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002219
hassoc9502432005-02-01 22:01:48 +00002220 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2221 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002222 }
2223 else
2224 BGP_EVENT_ADD (peer, BGP_Stop);
2225}
2226
2227/* Change specified peer flag. */
2228int
2229peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2230{
2231 int found;
2232 int size;
2233 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002234 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002235 struct peer_flag_action action;
2236
2237 memset (&action, 0, sizeof (struct peer_flag_action));
2238 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2239
2240 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2241
2242 /* No flag action is found. */
2243 if (! found)
2244 return BGP_ERR_INVALID_FLAG;
2245
2246 /* Not for peer-group member. */
2247 if (action.not_for_member && peer_group_active (peer))
2248 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2249
2250 /* When unset the peer-group member's flag we have to check
2251 peer-group configuration. */
2252 if (! set && peer_group_active (peer))
2253 if (CHECK_FLAG (peer->group->conf->flags, flag))
2254 {
2255 if (flag == PEER_FLAG_SHUTDOWN)
2256 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2257 else
2258 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2259 }
2260
2261 /* Flag conflict check. */
2262 if (set
2263 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2264 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2265 return BGP_ERR_PEER_FLAG_CONFLICT;
2266
2267 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2268 {
2269 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2270 return 0;
2271 if (! set && ! CHECK_FLAG (peer->flags, flag))
2272 return 0;
2273 }
2274
2275 if (set)
2276 SET_FLAG (peer->flags, flag);
2277 else
2278 UNSET_FLAG (peer->flags, flag);
2279
2280 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2281 {
2282 if (action.type == peer_change_reset)
2283 peer_flag_modify_action (peer, flag);
2284
2285 return 0;
2286 }
2287
2288 /* peer-group member updates. */
2289 group = peer->group;
2290
paul1eb8ef22005-04-07 07:30:20 +00002291 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002292 {
2293 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2294 continue;
2295
2296 if (! set && ! CHECK_FLAG (peer->flags, flag))
2297 continue;
2298
2299 if (set)
2300 SET_FLAG (peer->flags, flag);
2301 else
2302 UNSET_FLAG (peer->flags, flag);
2303
2304 if (action.type == peer_change_reset)
2305 peer_flag_modify_action (peer, flag);
2306 }
2307 return 0;
2308}
2309
2310int
2311peer_flag_set (struct peer *peer, u_int32_t flag)
2312{
2313 return peer_flag_modify (peer, flag, 1);
2314}
2315
2316int
2317peer_flag_unset (struct peer *peer, u_int32_t flag)
2318{
2319 return peer_flag_modify (peer, flag, 0);
2320}
2321
2322int
2323peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2324{
2325 if (peer->af_group[afi][safi])
2326 return 1;
2327 return 0;
2328}
2329
2330int
2331peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2332 int set)
2333{
2334 int found;
2335 int size;
paul1eb8ef22005-04-07 07:30:20 +00002336 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002337 struct peer_group *group;
2338 struct peer_flag_action action;
2339
2340 memset (&action, 0, sizeof (struct peer_flag_action));
2341 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2342
2343 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2344
2345 /* No flag action is found. */
2346 if (! found)
2347 return BGP_ERR_INVALID_FLAG;
2348
2349 /* Adress family must be activated. */
2350 if (! peer->afc[afi][safi])
2351 return BGP_ERR_PEER_INACTIVE;
2352
2353 /* Not for peer-group member. */
2354 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2355 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2356
2357 /* Spcecial check for reflector client. */
2358 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2359 && peer_sort (peer) != BGP_PEER_IBGP)
2360 return BGP_ERR_NOT_INTERNAL_PEER;
2361
2362 /* Spcecial check for remove-private-AS. */
2363 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2364 && peer_sort (peer) == BGP_PEER_IBGP)
2365 return BGP_ERR_REMOVE_PRIVATE_AS;
2366
2367 /* When unset the peer-group member's flag we have to check
2368 peer-group configuration. */
2369 if (! set && peer->af_group[afi][safi])
2370 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2371 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2372
2373 /* When current flag configuration is same as requested one. */
2374 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2375 {
2376 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2377 return 0;
2378 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2379 return 0;
2380 }
2381
2382 if (set)
2383 SET_FLAG (peer->af_flags[afi][safi], flag);
2384 else
2385 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2386
2387 /* Execute action when peer is established. */
2388 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2389 && peer->status == Established)
2390 {
2391 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2392 bgp_clear_adj_in (peer, afi, safi);
2393 else
hassoe0701b72004-05-20 09:19:34 +00002394 {
2395 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2396 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2397 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2398 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2399 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2400 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2401 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2402 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2403
2404 peer_change_action (peer, afi, safi, action.type);
2405 }
2406
paul718e3742002-12-13 20:15:29 +00002407 }
2408
2409 /* Peer group member updates. */
2410 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2411 {
2412 group = peer->group;
2413
paul1eb8ef22005-04-07 07:30:20 +00002414 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002415 {
2416 if (! peer->af_group[afi][safi])
2417 continue;
2418
2419 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2420 continue;
2421
2422 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2423 continue;
2424
2425 if (set)
2426 SET_FLAG (peer->af_flags[afi][safi], flag);
2427 else
2428 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2429
2430 if (peer->status == Established)
2431 {
2432 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2433 bgp_clear_adj_in (peer, afi, safi);
2434 else
hassoe0701b72004-05-20 09:19:34 +00002435 {
2436 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2437 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2438 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2439 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2440 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2441 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2442 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2443 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2444
2445 peer_change_action (peer, afi, safi, action.type);
2446 }
paul718e3742002-12-13 20:15:29 +00002447 }
2448 }
2449 }
2450 return 0;
2451}
2452
2453int
2454peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2455{
2456 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2457}
2458
2459int
2460peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2461{
2462 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2463}
2464
2465/* EBGP multihop configuration. */
2466int
2467peer_ebgp_multihop_set (struct peer *peer, int ttl)
2468{
2469 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002470 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002471
2472 if (peer_sort (peer) == BGP_PEER_IBGP)
2473 return 0;
2474
2475 peer->ttl = ttl;
2476
2477 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2478 {
pauleb821182004-05-01 08:44:08 +00002479 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2480 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002481 }
2482 else
2483 {
2484 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002485 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002486 {
2487 if (peer_sort (peer) == BGP_PEER_IBGP)
2488 continue;
paul718e3742002-12-13 20:15:29 +00002489
pauleb821182004-05-01 08:44:08 +00002490 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002491
pauleb821182004-05-01 08:44:08 +00002492 if (peer->fd >= 0)
2493 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2494 }
paul718e3742002-12-13 20:15:29 +00002495 }
2496 return 0;
2497}
2498
2499int
2500peer_ebgp_multihop_unset (struct peer *peer)
2501{
2502 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002503 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002504
2505 if (peer_sort (peer) == BGP_PEER_IBGP)
2506 return 0;
2507
2508 if (peer_group_active (peer))
2509 peer->ttl = peer->group->conf->ttl;
2510 else
2511 peer->ttl = 1;
2512
2513 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2514 {
pauleb821182004-05-01 08:44:08 +00002515 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2516 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002517 }
2518 else
2519 {
2520 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002521 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002522 {
2523 if (peer_sort (peer) == BGP_PEER_IBGP)
2524 continue;
paul718e3742002-12-13 20:15:29 +00002525
pauleb821182004-05-01 08:44:08 +00002526 peer->ttl = 1;
2527
2528 if (peer->fd >= 0)
2529 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2530 }
paul718e3742002-12-13 20:15:29 +00002531 }
2532 return 0;
2533}
2534
2535/* Neighbor description. */
2536int
2537peer_description_set (struct peer *peer, char *desc)
2538{
2539 if (peer->desc)
2540 XFREE (MTYPE_PEER_DESC, peer->desc);
2541
2542 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2543
2544 return 0;
2545}
2546
2547int
2548peer_description_unset (struct peer *peer)
2549{
2550 if (peer->desc)
2551 XFREE (MTYPE_PEER_DESC, peer->desc);
2552
2553 peer->desc = NULL;
2554
2555 return 0;
2556}
2557
2558/* Neighbor update-source. */
2559int
paulfd79ac92004-10-13 05:06:08 +00002560peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002561{
2562 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002563 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002564
2565 if (peer->update_if)
2566 {
2567 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2568 && strcmp (peer->update_if, ifname) == 0)
2569 return 0;
2570
2571 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2572 peer->update_if = NULL;
2573 }
2574
2575 if (peer->update_source)
2576 {
2577 sockunion_free (peer->update_source);
2578 peer->update_source = NULL;
2579 }
2580
2581 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2582
2583 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2584 {
2585 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002586 {
2587 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2588 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2589 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2590 }
paul718e3742002-12-13 20:15:29 +00002591 else
2592 BGP_EVENT_ADD (peer, BGP_Stop);
2593 return 0;
2594 }
2595
2596 /* peer-group member updates. */
2597 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002598 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002599 {
2600 if (peer->update_if)
2601 {
2602 if (strcmp (peer->update_if, ifname) == 0)
2603 continue;
2604
2605 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2606 peer->update_if = NULL;
2607 }
2608
2609 if (peer->update_source)
2610 {
2611 sockunion_free (peer->update_source);
2612 peer->update_source = NULL;
2613 }
2614
2615 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2616
2617 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002618 {
2619 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2620 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2621 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2622 }
paul718e3742002-12-13 20:15:29 +00002623 else
2624 BGP_EVENT_ADD (peer, BGP_Stop);
2625 }
2626 return 0;
2627}
2628
2629int
2630peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2631{
2632 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002633 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002634
2635 if (peer->update_source)
2636 {
2637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2638 && sockunion_cmp (peer->update_source, su) == 0)
2639 return 0;
2640 sockunion_free (peer->update_source);
2641 peer->update_source = NULL;
2642 }
2643
2644 if (peer->update_if)
2645 {
2646 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2647 peer->update_if = NULL;
2648 }
2649
2650 peer->update_source = sockunion_dup (su);
2651
2652 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2653 {
2654 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002655 {
2656 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2657 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2658 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2659 }
paul718e3742002-12-13 20:15:29 +00002660 else
2661 BGP_EVENT_ADD (peer, BGP_Stop);
2662 return 0;
2663 }
2664
2665 /* peer-group member updates. */
2666 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002667 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002668 {
2669 if (peer->update_source)
2670 {
2671 if (sockunion_cmp (peer->update_source, su) == 0)
2672 continue;
2673 sockunion_free (peer->update_source);
2674 peer->update_source = NULL;
2675 }
2676
2677 if (peer->update_if)
2678 {
2679 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2680 peer->update_if = NULL;
2681 }
2682
2683 peer->update_source = sockunion_dup (su);
2684
2685 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002686 {
2687 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2688 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2689 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2690 }
paul718e3742002-12-13 20:15:29 +00002691 else
2692 BGP_EVENT_ADD (peer, BGP_Stop);
2693 }
2694 return 0;
2695}
2696
2697int
2698peer_update_source_unset (struct peer *peer)
2699{
2700 union sockunion *su;
2701 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002702 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002703
2704 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2705 && ! peer->update_source
2706 && ! peer->update_if)
2707 return 0;
2708
2709 if (peer->update_source)
2710 {
2711 sockunion_free (peer->update_source);
2712 peer->update_source = NULL;
2713 }
2714 if (peer->update_if)
2715 {
2716 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2717 peer->update_if = NULL;
2718 }
2719
2720 if (peer_group_active (peer))
2721 {
2722 group = peer->group;
2723
2724 if (group->conf->update_source)
2725 {
2726 su = sockunion_dup (group->conf->update_source);
2727 peer->update_source = su;
2728 }
2729 else if (group->conf->update_if)
2730 peer->update_if =
2731 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2732 }
2733
2734 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2735 {
2736 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002737 {
2738 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2739 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2740 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2741 }
paul718e3742002-12-13 20:15:29 +00002742 else
2743 BGP_EVENT_ADD (peer, BGP_Stop);
2744 return 0;
2745 }
2746
2747 /* peer-group member updates. */
2748 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002749 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002750 {
2751 if (! peer->update_source && ! peer->update_if)
2752 continue;
2753
2754 if (peer->update_source)
2755 {
2756 sockunion_free (peer->update_source);
2757 peer->update_source = NULL;
2758 }
2759
2760 if (peer->update_if)
2761 {
2762 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2763 peer->update_if = NULL;
2764 }
2765
2766 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002767 {
2768 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2769 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2770 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2771 }
paul718e3742002-12-13 20:15:29 +00002772 else
2773 BGP_EVENT_ADD (peer, BGP_Stop);
2774 }
2775 return 0;
2776}
2777
2778int
2779peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002780 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002781{
2782 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002783 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002784
2785 /* Adress family must be activated. */
2786 if (! peer->afc[afi][safi])
2787 return BGP_ERR_PEER_INACTIVE;
2788
2789 /* Default originate can't be used for peer group memeber. */
2790 if (peer_is_group_member (peer, afi, safi))
2791 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2792
2793 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2794 || (rmap && ! peer->default_rmap[afi][safi].name)
2795 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2796 {
2797 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2798
2799 if (rmap)
2800 {
2801 if (peer->default_rmap[afi][safi].name)
2802 free (peer->default_rmap[afi][safi].name);
2803 peer->default_rmap[afi][safi].name = strdup (rmap);
2804 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2805 }
2806 }
2807
2808 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2809 {
2810 if (peer->status == Established && peer->afc_nego[afi][safi])
2811 bgp_default_originate (peer, afi, safi, 0);
2812 return 0;
2813 }
2814
2815 /* peer-group member updates. */
2816 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002817 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002818 {
2819 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2820
2821 if (rmap)
2822 {
2823 if (peer->default_rmap[afi][safi].name)
2824 free (peer->default_rmap[afi][safi].name);
2825 peer->default_rmap[afi][safi].name = strdup (rmap);
2826 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2827 }
2828
2829 if (peer->status == Established && peer->afc_nego[afi][safi])
2830 bgp_default_originate (peer, afi, safi, 0);
2831 }
2832 return 0;
2833}
2834
2835int
2836peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2837{
2838 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002839 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002840
2841 /* Adress family must be activated. */
2842 if (! peer->afc[afi][safi])
2843 return BGP_ERR_PEER_INACTIVE;
2844
2845 /* Default originate can't be used for peer group memeber. */
2846 if (peer_is_group_member (peer, afi, safi))
2847 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2848
2849 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2850 {
2851 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2852
2853 if (peer->default_rmap[afi][safi].name)
2854 free (peer->default_rmap[afi][safi].name);
2855 peer->default_rmap[afi][safi].name = NULL;
2856 peer->default_rmap[afi][safi].map = NULL;
2857 }
2858
2859 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2860 {
2861 if (peer->status == Established && peer->afc_nego[afi][safi])
2862 bgp_default_originate (peer, afi, safi, 1);
2863 return 0;
2864 }
2865
2866 /* peer-group member updates. */
2867 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002868 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002869 {
2870 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2871
2872 if (peer->default_rmap[afi][safi].name)
2873 free (peer->default_rmap[afi][safi].name);
2874 peer->default_rmap[afi][safi].name = NULL;
2875 peer->default_rmap[afi][safi].map = NULL;
2876
2877 if (peer->status == Established && peer->afc_nego[afi][safi])
2878 bgp_default_originate (peer, afi, safi, 1);
2879 }
2880 return 0;
2881}
2882
2883int
2884peer_port_set (struct peer *peer, u_int16_t port)
2885{
2886 peer->port = port;
2887 return 0;
2888}
2889
2890int
2891peer_port_unset (struct peer *peer)
2892{
2893 peer->port = BGP_PORT_DEFAULT;
2894 return 0;
2895}
2896
2897/* neighbor weight. */
2898int
2899peer_weight_set (struct peer *peer, u_int16_t weight)
2900{
2901 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002902 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002903
2904 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2905 peer->weight = weight;
2906
2907 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2908 return 0;
2909
2910 /* peer-group member updates. */
2911 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002912 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002913 {
2914 peer->weight = group->conf->weight;
2915 }
2916 return 0;
2917}
2918
2919int
2920peer_weight_unset (struct peer *peer)
2921{
2922 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002923 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002924
2925 /* Set default weight. */
2926 if (peer_group_active (peer))
2927 peer->weight = peer->group->conf->weight;
2928 else
2929 peer->weight = 0;
2930
2931 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2932
2933 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2934 return 0;
2935
2936 /* peer-group member updates. */
2937 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002938 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002939 {
2940 peer->weight = 0;
2941 }
2942 return 0;
2943}
2944
2945int
2946peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2947{
2948 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002949 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002950
2951 /* Not for peer group memeber. */
2952 if (peer_group_active (peer))
2953 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2954
2955 /* keepalive value check. */
2956 if (keepalive > 65535)
2957 return BGP_ERR_INVALID_VALUE;
2958
2959 /* Holdtime value check. */
2960 if (holdtime > 65535)
2961 return BGP_ERR_INVALID_VALUE;
2962
2963 /* Holdtime value must be either 0 or greater than 3. */
2964 if (holdtime < 3 && holdtime != 0)
2965 return BGP_ERR_INVALID_VALUE;
2966
2967 /* Set value to the configuration. */
2968 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2969 peer->holdtime = holdtime;
2970 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2971
2972 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2973 return 0;
2974
2975 /* peer-group member updates. */
2976 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002977 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002978 {
2979 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2980 peer->holdtime = group->conf->holdtime;
2981 peer->keepalive = group->conf->keepalive;
2982 }
2983 return 0;
2984}
2985
2986int
2987peer_timers_unset (struct peer *peer)
2988{
2989 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002990 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002991
2992 if (peer_group_active (peer))
2993 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2994
2995 /* Clear configuration. */
2996 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2997 peer->keepalive = 0;
2998 peer->holdtime = 0;
2999
3000 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3001 return 0;
3002
3003 /* peer-group member updates. */
3004 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003005 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003006 {
3007 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3008 peer->holdtime = 0;
3009 peer->keepalive = 0;
3010 }
3011
3012 return 0;
3013}
3014
3015int
3016peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3017{
3018 if (peer_group_active (peer))
3019 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3020
3021 if (connect > 65535)
3022 return BGP_ERR_INVALID_VALUE;
3023
3024 /* Set value to the configuration. */
3025 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3026 peer->connect = connect;
3027
3028 /* Set value to timer setting. */
3029 peer->v_connect = connect;
3030
3031 return 0;
3032}
3033
3034int
3035peer_timers_connect_unset (struct peer *peer)
3036{
3037 if (peer_group_active (peer))
3038 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3039
3040 /* Clear configuration. */
3041 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3042 peer->connect = 0;
3043
3044 /* Set timer setting to default value. */
3045 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3046
3047 return 0;
3048}
3049
3050int
3051peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3052{
3053 if (peer_group_active (peer))
3054 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3055
3056 if (routeadv > 600)
3057 return BGP_ERR_INVALID_VALUE;
3058
3059 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3060 peer->routeadv = routeadv;
3061 peer->v_routeadv = routeadv;
3062
3063 return 0;
3064}
3065
3066int
3067peer_advertise_interval_unset (struct peer *peer)
3068{
3069 if (peer_group_active (peer))
3070 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3071
3072 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3073 peer->routeadv = 0;
3074
3075 if (peer_sort (peer) == BGP_PEER_IBGP)
3076 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3077 else
3078 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3079
3080 return 0;
3081}
3082
paul718e3742002-12-13 20:15:29 +00003083/* neighbor interface */
3084int
paulfd79ac92004-10-13 05:06:08 +00003085peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003086{
3087 if (peer->ifname)
3088 free (peer->ifname);
3089 peer->ifname = strdup (str);
3090
3091 return 0;
3092}
3093
3094int
3095peer_interface_unset (struct peer *peer)
3096{
3097 if (peer->ifname)
3098 free (peer->ifname);
3099 peer->ifname = NULL;
3100
3101 return 0;
3102}
3103
3104/* Allow-as in. */
3105int
3106peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3107{
3108 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003109 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003110
3111 if (allow_num < 1 || allow_num > 10)
3112 return BGP_ERR_INVALID_VALUE;
3113
3114 if (peer->allowas_in[afi][safi] != allow_num)
3115 {
3116 peer->allowas_in[afi][safi] = allow_num;
3117 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3118 peer_change_action (peer, afi, safi, peer_change_reset_in);
3119 }
3120
3121 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3122 return 0;
3123
3124 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003125 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003126 {
3127 if (peer->allowas_in[afi][safi] != allow_num)
3128 {
3129 peer->allowas_in[afi][safi] = allow_num;
3130 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3131 peer_change_action (peer, afi, safi, peer_change_reset_in);
3132 }
3133
3134 }
3135 return 0;
3136}
3137
3138int
3139peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3140{
3141 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003142 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003143
3144 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3145 {
3146 peer->allowas_in[afi][safi] = 0;
3147 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3148 }
3149
3150 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3151 return 0;
3152
3153 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003154 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003155 {
3156 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3157 {
3158 peer->allowas_in[afi][safi] = 0;
3159 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3160 }
3161 }
3162 return 0;
3163}
3164
3165int
3166peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3167{
3168 struct bgp *bgp = peer->bgp;
3169 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003170 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003171
3172 if (peer_sort (peer) != BGP_PEER_EBGP
3173 && peer_sort (peer) != BGP_PEER_INTERNAL)
3174 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3175
3176 if (bgp->as == as)
3177 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3178
3179 if (peer_group_active (peer))
3180 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3181
3182 if (peer->change_local_as == as &&
3183 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3184 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3185 return 0;
3186
3187 peer->change_local_as = as;
3188 if (no_prepend)
3189 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3190 else
3191 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3192
3193 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3194 {
3195 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003196 {
3197 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3198 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3199 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3200 }
paul718e3742002-12-13 20:15:29 +00003201 else
3202 BGP_EVENT_ADD (peer, BGP_Stop);
3203
3204 return 0;
3205 }
3206
3207 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003208 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003209 {
3210 peer->change_local_as = as;
3211 if (no_prepend)
3212 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3213 else
3214 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3215
3216 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003217 {
3218 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3219 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3220 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3221 }
paul718e3742002-12-13 20:15:29 +00003222 else
3223 BGP_EVENT_ADD (peer, BGP_Stop);
3224 }
3225
3226 return 0;
3227}
3228
3229int
3230peer_local_as_unset (struct peer *peer)
3231{
3232 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003233 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003234
3235 if (peer_group_active (peer))
3236 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3237
3238 if (! peer->change_local_as)
3239 return 0;
3240
3241 peer->change_local_as = 0;
3242 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3243
3244 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3245 {
3246 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003247 {
3248 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3249 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3250 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3251 }
paul718e3742002-12-13 20:15:29 +00003252 else
3253 BGP_EVENT_ADD (peer, BGP_Stop);
3254
3255 return 0;
3256 }
3257
3258 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003259 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003260 {
3261 peer->change_local_as = 0;
3262 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3263
3264 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003265 {
3266 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3267 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3268 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3269 }
paul718e3742002-12-13 20:15:29 +00003270 else
3271 BGP_EVENT_ADD (peer, BGP_Stop);
3272 }
3273 return 0;
3274}
3275
3276/* Set distribute list to the peer. */
3277int
3278peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003279 const char *name)
paul718e3742002-12-13 20:15:29 +00003280{
3281 struct bgp_filter *filter;
3282 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003283 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003284
3285 if (! peer->afc[afi][safi])
3286 return BGP_ERR_PEER_INACTIVE;
3287
3288 if (direct != FILTER_IN && direct != FILTER_OUT)
3289 return BGP_ERR_INVALID_VALUE;
3290
3291 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3292 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3293
3294 filter = &peer->filter[afi][safi];
3295
3296 if (filter->plist[direct].name)
3297 return BGP_ERR_PEER_FILTER_CONFLICT;
3298
3299 if (filter->dlist[direct].name)
3300 free (filter->dlist[direct].name);
3301 filter->dlist[direct].name = strdup (name);
3302 filter->dlist[direct].alist = access_list_lookup (afi, name);
3303
3304 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3305 return 0;
3306
3307 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003308 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003309 {
3310 filter = &peer->filter[afi][safi];
3311
3312 if (! peer->af_group[afi][safi])
3313 continue;
3314
3315 if (filter->dlist[direct].name)
3316 free (filter->dlist[direct].name);
3317 filter->dlist[direct].name = strdup (name);
3318 filter->dlist[direct].alist = access_list_lookup (afi, name);
3319 }
3320
3321 return 0;
3322}
3323
3324int
3325peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3326{
3327 struct bgp_filter *filter;
3328 struct bgp_filter *gfilter;
3329 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003331
3332 if (! peer->afc[afi][safi])
3333 return BGP_ERR_PEER_INACTIVE;
3334
3335 if (direct != FILTER_IN && direct != FILTER_OUT)
3336 return BGP_ERR_INVALID_VALUE;
3337
3338 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3339 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3340
3341 filter = &peer->filter[afi][safi];
3342
3343 /* apply peer-group filter */
3344 if (peer->af_group[afi][safi])
3345 {
3346 gfilter = &peer->group->conf->filter[afi][safi];
3347
3348 if (gfilter->dlist[direct].name)
3349 {
3350 if (filter->dlist[direct].name)
3351 free (filter->dlist[direct].name);
3352 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3353 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3354 return 0;
3355 }
3356 }
3357
3358 if (filter->dlist[direct].name)
3359 free (filter->dlist[direct].name);
3360 filter->dlist[direct].name = NULL;
3361 filter->dlist[direct].alist = NULL;
3362
3363 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3364 return 0;
3365
3366 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003367 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003368 {
3369 filter = &peer->filter[afi][safi];
3370
3371 if (! peer->af_group[afi][safi])
3372 continue;
3373
3374 if (filter->dlist[direct].name)
3375 free (filter->dlist[direct].name);
3376 filter->dlist[direct].name = NULL;
3377 filter->dlist[direct].alist = NULL;
3378 }
3379
3380 return 0;
3381}
3382
3383/* Update distribute list. */
3384void
3385peer_distribute_update (struct access_list *access)
3386{
3387 afi_t afi;
3388 safi_t safi;
3389 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003390 struct listnode *mnode, *mnnode;
3391 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003392 struct bgp *bgp;
3393 struct peer *peer;
3394 struct peer_group *group;
3395 struct bgp_filter *filter;
3396
paul1eb8ef22005-04-07 07:30:20 +00003397 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003398 {
paul1eb8ef22005-04-07 07:30:20 +00003399 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003400 {
3401 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3402 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3403 {
3404 filter = &peer->filter[afi][safi];
3405
3406 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3407 {
3408 if (filter->dlist[direct].name)
3409 filter->dlist[direct].alist =
3410 access_list_lookup (afi, filter->dlist[direct].name);
3411 else
3412 filter->dlist[direct].alist = NULL;
3413 }
3414 }
3415 }
paul1eb8ef22005-04-07 07:30:20 +00003416 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003417 {
3418 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3419 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3420 {
3421 filter = &group->conf->filter[afi][safi];
3422
3423 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3424 {
3425 if (filter->dlist[direct].name)
3426 filter->dlist[direct].alist =
3427 access_list_lookup (afi, filter->dlist[direct].name);
3428 else
3429 filter->dlist[direct].alist = NULL;
3430 }
3431 }
3432 }
3433 }
3434}
3435
3436/* Set prefix list to the peer. */
3437int
3438peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003439 const char *name)
paul718e3742002-12-13 20:15:29 +00003440{
3441 struct bgp_filter *filter;
3442 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003443 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003444
3445 if (! peer->afc[afi][safi])
3446 return BGP_ERR_PEER_INACTIVE;
3447
3448 if (direct != FILTER_IN && direct != FILTER_OUT)
3449 return BGP_ERR_INVALID_VALUE;
3450
3451 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3452 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3453
3454 filter = &peer->filter[afi][safi];
3455
3456 if (filter->dlist[direct].name)
3457 return BGP_ERR_PEER_FILTER_CONFLICT;
3458
3459 if (filter->plist[direct].name)
3460 free (filter->plist[direct].name);
3461 filter->plist[direct].name = strdup (name);
3462 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3463
3464 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3465 return 0;
3466
3467 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003468 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003469 {
3470 filter = &peer->filter[afi][safi];
3471
3472 if (! peer->af_group[afi][safi])
3473 continue;
3474
3475 if (filter->plist[direct].name)
3476 free (filter->plist[direct].name);
3477 filter->plist[direct].name = strdup (name);
3478 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3479 }
3480 return 0;
3481}
3482
3483int
3484peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3485{
3486 struct bgp_filter *filter;
3487 struct bgp_filter *gfilter;
3488 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003489 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003490
3491 if (! peer->afc[afi][safi])
3492 return BGP_ERR_PEER_INACTIVE;
3493
3494 if (direct != FILTER_IN && direct != FILTER_OUT)
3495 return BGP_ERR_INVALID_VALUE;
3496
3497 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3498 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3499
3500 filter = &peer->filter[afi][safi];
3501
3502 /* apply peer-group filter */
3503 if (peer->af_group[afi][safi])
3504 {
3505 gfilter = &peer->group->conf->filter[afi][safi];
3506
3507 if (gfilter->plist[direct].name)
3508 {
3509 if (filter->plist[direct].name)
3510 free (filter->plist[direct].name);
3511 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3512 filter->plist[direct].plist = gfilter->plist[direct].plist;
3513 return 0;
3514 }
3515 }
3516
3517 if (filter->plist[direct].name)
3518 free (filter->plist[direct].name);
3519 filter->plist[direct].name = NULL;
3520 filter->plist[direct].plist = NULL;
3521
3522 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3523 return 0;
3524
3525 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003526 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003527 {
3528 filter = &peer->filter[afi][safi];
3529
3530 if (! peer->af_group[afi][safi])
3531 continue;
3532
3533 if (filter->plist[direct].name)
3534 free (filter->plist[direct].name);
3535 filter->plist[direct].name = NULL;
3536 filter->plist[direct].plist = NULL;
3537 }
3538
3539 return 0;
3540}
3541
3542/* Update prefix-list list. */
3543void
3544peer_prefix_list_update (struct prefix_list *plist)
3545{
paul1eb8ef22005-04-07 07:30:20 +00003546 struct listnode *mnode, *mnnode;
3547 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003548 struct bgp *bgp;
3549 struct peer *peer;
3550 struct peer_group *group;
3551 struct bgp_filter *filter;
3552 afi_t afi;
3553 safi_t safi;
3554 int direct;
3555
paul1eb8ef22005-04-07 07:30:20 +00003556 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003557 {
paul1eb8ef22005-04-07 07:30:20 +00003558 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003559 {
3560 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3561 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3562 {
3563 filter = &peer->filter[afi][safi];
3564
3565 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3566 {
3567 if (filter->plist[direct].name)
3568 filter->plist[direct].plist =
3569 prefix_list_lookup (afi, filter->plist[direct].name);
3570 else
3571 filter->plist[direct].plist = NULL;
3572 }
3573 }
3574 }
paul1eb8ef22005-04-07 07:30:20 +00003575 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003576 {
3577 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3578 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3579 {
3580 filter = &group->conf->filter[afi][safi];
3581
3582 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3583 {
3584 if (filter->plist[direct].name)
3585 filter->plist[direct].plist =
3586 prefix_list_lookup (afi, filter->plist[direct].name);
3587 else
3588 filter->plist[direct].plist = NULL;
3589 }
3590 }
3591 }
3592 }
3593}
3594
3595int
3596peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003597 const char *name)
paul718e3742002-12-13 20:15:29 +00003598{
3599 struct bgp_filter *filter;
3600 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003601 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003602
3603 if (! peer->afc[afi][safi])
3604 return BGP_ERR_PEER_INACTIVE;
3605
3606 if (direct != FILTER_IN && direct != FILTER_OUT)
3607 return BGP_ERR_INVALID_VALUE;
3608
3609 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3610 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3611
3612 filter = &peer->filter[afi][safi];
3613
3614 if (filter->aslist[direct].name)
3615 free (filter->aslist[direct].name);
3616 filter->aslist[direct].name = strdup (name);
3617 filter->aslist[direct].aslist = as_list_lookup (name);
3618
3619 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3620 return 0;
3621
3622 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003623 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003624 {
3625 filter = &peer->filter[afi][safi];
3626
3627 if (! peer->af_group[afi][safi])
3628 continue;
3629
3630 if (filter->aslist[direct].name)
3631 free (filter->aslist[direct].name);
3632 filter->aslist[direct].name = strdup (name);
3633 filter->aslist[direct].aslist = as_list_lookup (name);
3634 }
3635 return 0;
3636}
3637
3638int
3639peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3640{
3641 struct bgp_filter *filter;
3642 struct bgp_filter *gfilter;
3643 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003644 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003645
3646 if (! peer->afc[afi][safi])
3647 return BGP_ERR_PEER_INACTIVE;
3648
hassob5f29602005-05-25 21:00:28 +00003649 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003650 return BGP_ERR_INVALID_VALUE;
3651
hassob5f29602005-05-25 21:00:28 +00003652 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003653 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3654
3655 filter = &peer->filter[afi][safi];
3656
3657 /* apply peer-group filter */
3658 if (peer->af_group[afi][safi])
3659 {
3660 gfilter = &peer->group->conf->filter[afi][safi];
3661
3662 if (gfilter->aslist[direct].name)
3663 {
3664 if (filter->aslist[direct].name)
3665 free (filter->aslist[direct].name);
3666 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3667 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3668 return 0;
3669 }
3670 }
3671
3672 if (filter->aslist[direct].name)
3673 free (filter->aslist[direct].name);
3674 filter->aslist[direct].name = NULL;
3675 filter->aslist[direct].aslist = NULL;
3676
3677 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3678 return 0;
3679
3680 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003681 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003682 {
3683 filter = &peer->filter[afi][safi];
3684
3685 if (! peer->af_group[afi][safi])
3686 continue;
3687
3688 if (filter->aslist[direct].name)
3689 free (filter->aslist[direct].name);
3690 filter->aslist[direct].name = NULL;
3691 filter->aslist[direct].aslist = NULL;
3692 }
3693
3694 return 0;
3695}
3696
3697void
3698peer_aslist_update ()
3699{
3700 afi_t afi;
3701 safi_t safi;
3702 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003703 struct listnode *mnode, *mnnode;
3704 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003705 struct bgp *bgp;
3706 struct peer *peer;
3707 struct peer_group *group;
3708 struct bgp_filter *filter;
3709
paul1eb8ef22005-04-07 07:30:20 +00003710 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003711 {
paul1eb8ef22005-04-07 07:30:20 +00003712 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003713 {
3714 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3715 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3716 {
3717 filter = &peer->filter[afi][safi];
3718
3719 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3720 {
3721 if (filter->aslist[direct].name)
3722 filter->aslist[direct].aslist =
3723 as_list_lookup (filter->aslist[direct].name);
3724 else
3725 filter->aslist[direct].aslist = NULL;
3726 }
3727 }
3728 }
paul1eb8ef22005-04-07 07:30:20 +00003729 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003730 {
3731 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3732 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3733 {
3734 filter = &group->conf->filter[afi][safi];
3735
3736 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3737 {
3738 if (filter->aslist[direct].name)
3739 filter->aslist[direct].aslist =
3740 as_list_lookup (filter->aslist[direct].name);
3741 else
3742 filter->aslist[direct].aslist = NULL;
3743 }
3744 }
3745 }
3746 }
3747}
3748
3749/* Set route-map to the peer. */
3750int
3751peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003752 const char *name)
paul718e3742002-12-13 20:15:29 +00003753{
3754 struct bgp_filter *filter;
3755 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003756 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003757
3758 if (! peer->afc[afi][safi])
3759 return BGP_ERR_PEER_INACTIVE;
3760
paulfee0f4c2004-09-13 05:12:46 +00003761 if (direct != RMAP_IN && direct != RMAP_OUT &&
3762 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003763 return BGP_ERR_INVALID_VALUE;
3764
paulfee0f4c2004-09-13 05:12:46 +00003765 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3766 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003767 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3768
3769 filter = &peer->filter[afi][safi];
3770
3771 if (filter->map[direct].name)
3772 free (filter->map[direct].name);
3773
3774 filter->map[direct].name = strdup (name);
3775 filter->map[direct].map = route_map_lookup_by_name (name);
3776
3777 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3778 return 0;
3779
3780 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003781 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003782 {
3783 filter = &peer->filter[afi][safi];
3784
3785 if (! peer->af_group[afi][safi])
3786 continue;
3787
3788 if (filter->map[direct].name)
3789 free (filter->map[direct].name);
3790 filter->map[direct].name = strdup (name);
3791 filter->map[direct].map = route_map_lookup_by_name (name);
3792 }
3793 return 0;
3794}
3795
3796/* Unset route-map from the peer. */
3797int
3798peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3799{
3800 struct bgp_filter *filter;
3801 struct bgp_filter *gfilter;
3802 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003803 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003804
3805 if (! peer->afc[afi][safi])
3806 return BGP_ERR_PEER_INACTIVE;
3807
hassob5f29602005-05-25 21:00:28 +00003808 if (direct != RMAP_IN && direct != RMAP_OUT &&
3809 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003810 return BGP_ERR_INVALID_VALUE;
3811
hassob5f29602005-05-25 21:00:28 +00003812 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3813 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003814 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3815
3816 filter = &peer->filter[afi][safi];
3817
3818 /* apply peer-group filter */
3819 if (peer->af_group[afi][safi])
3820 {
3821 gfilter = &peer->group->conf->filter[afi][safi];
3822
3823 if (gfilter->map[direct].name)
3824 {
3825 if (filter->map[direct].name)
3826 free (filter->map[direct].name);
3827 filter->map[direct].name = strdup (gfilter->map[direct].name);
3828 filter->map[direct].map = gfilter->map[direct].map;
3829 return 0;
3830 }
3831 }
3832
3833 if (filter->map[direct].name)
3834 free (filter->map[direct].name);
3835 filter->map[direct].name = NULL;
3836 filter->map[direct].map = NULL;
3837
3838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3839 return 0;
3840
3841 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003842 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003843 {
3844 filter = &peer->filter[afi][safi];
3845
3846 if (! peer->af_group[afi][safi])
3847 continue;
3848
3849 if (filter->map[direct].name)
3850 free (filter->map[direct].name);
3851 filter->map[direct].name = NULL;
3852 filter->map[direct].map = NULL;
3853 }
3854 return 0;
3855}
3856
3857/* Set unsuppress-map to the peer. */
3858int
paulfd79ac92004-10-13 05:06:08 +00003859peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3860 const char *name)
paul718e3742002-12-13 20:15:29 +00003861{
3862 struct bgp_filter *filter;
3863 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003864 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003865
3866 if (! peer->afc[afi][safi])
3867 return BGP_ERR_PEER_INACTIVE;
3868
3869 if (peer_is_group_member (peer, afi, safi))
3870 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3871
3872 filter = &peer->filter[afi][safi];
3873
3874 if (filter->usmap.name)
3875 free (filter->usmap.name);
3876
3877 filter->usmap.name = strdup (name);
3878 filter->usmap.map = route_map_lookup_by_name (name);
3879
3880 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3881 return 0;
3882
3883 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003884 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003885 {
3886 filter = &peer->filter[afi][safi];
3887
3888 if (! peer->af_group[afi][safi])
3889 continue;
3890
3891 if (filter->usmap.name)
3892 free (filter->usmap.name);
3893 filter->usmap.name = strdup (name);
3894 filter->usmap.map = route_map_lookup_by_name (name);
3895 }
3896 return 0;
3897}
3898
3899/* Unset route-map from the peer. */
3900int
3901peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3902{
3903 struct bgp_filter *filter;
3904 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003905 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003906
3907 if (! peer->afc[afi][safi])
3908 return BGP_ERR_PEER_INACTIVE;
3909
3910 if (peer_is_group_member (peer, afi, safi))
3911 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3912
3913 filter = &peer->filter[afi][safi];
3914
3915 if (filter->usmap.name)
3916 free (filter->usmap.name);
3917 filter->usmap.name = NULL;
3918 filter->usmap.map = NULL;
3919
3920 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3921 return 0;
3922
3923 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003924 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003925 {
3926 filter = &peer->filter[afi][safi];
3927
3928 if (! peer->af_group[afi][safi])
3929 continue;
3930
3931 if (filter->usmap.name)
3932 free (filter->usmap.name);
3933 filter->usmap.name = NULL;
3934 filter->usmap.map = NULL;
3935 }
3936 return 0;
3937}
3938
3939int
3940peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00003941 u_int32_t max, u_char threshold,
3942 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00003943{
3944 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003945 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003946
3947 if (! peer->afc[afi][safi])
3948 return BGP_ERR_PEER_INACTIVE;
3949
3950 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3951 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003952 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003953 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003954 if (warning)
3955 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3956 else
3957 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3958
3959 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3960 return 0;
3961
3962 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003963 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003964 {
3965 if (! peer->af_group[afi][safi])
3966 continue;
3967
3968 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3969 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003970 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003971 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003972 if (warning)
3973 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3974 else
3975 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3976 }
3977 return 0;
3978}
3979
3980int
3981peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3982{
3983 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003984 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003985
3986 if (! peer->afc[afi][safi])
3987 return BGP_ERR_PEER_INACTIVE;
3988
3989 /* apply peer-group config */
3990 if (peer->af_group[afi][safi])
3991 {
3992 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3993 PEER_FLAG_MAX_PREFIX))
3994 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3995 else
3996 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3997
3998 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3999 PEER_FLAG_MAX_PREFIX_WARNING))
4000 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4001 else
4002 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4003
4004 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004005 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004006 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004007 return 0;
4008 }
4009
4010 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4011 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4012 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004013 peer->pmax_threshold[afi][safi] = 0;
4014 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004015
4016 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4017 return 0;
4018
4019 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004020 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004021 {
4022 if (! peer->af_group[afi][safi])
4023 continue;
4024
4025 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4026 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4027 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004028 peer->pmax_threshold[afi][safi] = 0;
4029 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004030 }
4031 return 0;
4032}
4033
4034int
4035peer_clear (struct peer *peer)
4036{
4037 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4038 {
hasso0a486e52005-02-01 20:57:17 +00004039 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4040 {
4041 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4042 if (peer->t_pmax_restart)
4043 {
4044 BGP_TIMER_OFF (peer->t_pmax_restart);
4045 if (BGP_DEBUG (events, EVENTS))
4046 zlog_debug ("%s Maximum-prefix restart timer canceled",
4047 peer->host);
4048 }
4049 BGP_EVENT_ADD (peer, BGP_Start);
4050 return 0;
4051 }
4052
paul718e3742002-12-13 20:15:29 +00004053 peer->v_start = BGP_INIT_START_TIMER;
4054 if (peer->status == Established)
4055 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4056 BGP_NOTIFY_CEASE_ADMIN_RESET);
4057 else
4058 BGP_EVENT_ADD (peer, BGP_Stop);
4059 }
4060 return 0;
4061}
4062
4063int
4064peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4065 enum bgp_clear_type stype)
4066{
4067 if (peer->status != Established)
4068 return 0;
4069
4070 if (! peer->afc[afi][safi])
4071 return BGP_ERR_AF_UNCONFIGURED;
4072
paulfee0f4c2004-09-13 05:12:46 +00004073 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4074 {
4075 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4076 return 0;
4077 bgp_check_local_routes_rsclient (peer, afi, safi);
4078 bgp_soft_reconfig_rsclient (peer, afi, safi);
4079 }
4080
paul718e3742002-12-13 20:15:29 +00004081 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4082 bgp_announce_route (peer, afi, safi);
4083
4084 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4085 {
4086 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4087 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4088 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4089 {
4090 struct bgp_filter *filter = &peer->filter[afi][safi];
4091 u_char prefix_type;
4092
4093 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4094 prefix_type = ORF_TYPE_PREFIX;
4095 else
4096 prefix_type = ORF_TYPE_PREFIX_OLD;
4097
4098 if (filter->plist[FILTER_IN].plist)
4099 {
4100 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4101 bgp_route_refresh_send (peer, afi, safi,
4102 prefix_type, REFRESH_DEFER, 1);
4103 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4104 REFRESH_IMMEDIATE, 0);
4105 }
4106 else
4107 {
4108 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4109 bgp_route_refresh_send (peer, afi, safi,
4110 prefix_type, REFRESH_IMMEDIATE, 1);
4111 else
4112 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4113 }
4114 return 0;
4115 }
4116 }
4117
4118 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4119 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4120 {
4121 /* If neighbor has soft reconfiguration inbound flag.
4122 Use Adj-RIB-In database. */
4123 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4124 bgp_soft_reconfig_in (peer, afi, safi);
4125 else
4126 {
4127 /* If neighbor has route refresh capability, send route refresh
4128 message to the peer. */
4129 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4130 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4131 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4132 else
4133 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4134 }
4135 }
4136 return 0;
4137}
4138
paulfd79ac92004-10-13 05:06:08 +00004139/* Display peer uptime.*/
4140/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004141char *
4142peer_uptime (time_t uptime2, char *buf, size_t len)
4143{
4144 time_t uptime1;
4145 struct tm *tm;
4146
4147 /* Check buffer length. */
4148 if (len < BGP_UPTIME_LEN)
4149 {
gdtc29fdba2004-12-09 14:46:46 +00004150 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004151 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004152 /* XXX: should return status instead of buf... */
4153 snprintf (buf, len, "<error> ");
4154 return buf;
paul718e3742002-12-13 20:15:29 +00004155 }
4156
4157 /* If there is no connection has been done before print `never'. */
4158 if (uptime2 == 0)
4159 {
4160 snprintf (buf, len, "never ");
4161 return buf;
4162 }
4163
4164 /* Get current time. */
4165 uptime1 = time (NULL);
4166 uptime1 -= uptime2;
4167 tm = gmtime (&uptime1);
4168
4169 /* Making formatted timer strings. */
4170#define ONE_DAY_SECOND 60*60*24
4171#define ONE_WEEK_SECOND 60*60*24*7
4172
4173 if (uptime1 < ONE_DAY_SECOND)
4174 snprintf (buf, len, "%02d:%02d:%02d",
4175 tm->tm_hour, tm->tm_min, tm->tm_sec);
4176 else if (uptime1 < ONE_WEEK_SECOND)
4177 snprintf (buf, len, "%dd%02dh%02dm",
4178 tm->tm_yday, tm->tm_hour, tm->tm_min);
4179 else
4180 snprintf (buf, len, "%02dw%dd%02dh",
4181 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4182 return buf;
4183}
4184
4185void
4186bgp_config_write_filter (struct vty *vty, struct peer *peer,
4187 afi_t afi, safi_t safi)
4188{
4189 struct bgp_filter *filter;
4190 struct bgp_filter *gfilter = NULL;
4191 char *addr;
4192 int in = FILTER_IN;
4193 int out = FILTER_OUT;
4194
4195 addr = peer->host;
4196 filter = &peer->filter[afi][safi];
4197 if (peer->af_group[afi][safi])
4198 gfilter = &peer->group->conf->filter[afi][safi];
4199
4200 /* distribute-list. */
4201 if (filter->dlist[in].name)
4202 if (! gfilter || ! gfilter->dlist[in].name
4203 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4204 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4205 filter->dlist[in].name, VTY_NEWLINE);
4206 if (filter->dlist[out].name && ! gfilter)
4207 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4208 filter->dlist[out].name, VTY_NEWLINE);
4209
4210 /* prefix-list. */
4211 if (filter->plist[in].name)
4212 if (! gfilter || ! gfilter->plist[in].name
4213 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4214 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4215 filter->plist[in].name, VTY_NEWLINE);
4216 if (filter->plist[out].name && ! gfilter)
4217 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4218 filter->plist[out].name, VTY_NEWLINE);
4219
4220 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004221 if (filter->map[RMAP_IN].name)
4222 if (! gfilter || ! gfilter->map[RMAP_IN].name
4223 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004224 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004225 filter->map[RMAP_IN].name, VTY_NEWLINE);
4226 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004227 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004228 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4229 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4230 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4231 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4232 if (filter->map[RMAP_EXPORT].name)
4233 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4234 || strcmp (filter->map[RMAP_EXPORT].name,
4235 gfilter->map[RMAP_EXPORT].name) != 0)
4236 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4237 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004238
4239 /* unsuppress-map */
4240 if (filter->usmap.name && ! gfilter)
4241 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4242 filter->usmap.name, VTY_NEWLINE);
4243
4244 /* filter-list. */
4245 if (filter->aslist[in].name)
4246 if (! gfilter || ! gfilter->aslist[in].name
4247 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4248 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4249 filter->aslist[in].name, VTY_NEWLINE);
4250 if (filter->aslist[out].name && ! gfilter)
4251 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4252 filter->aslist[out].name, VTY_NEWLINE);
4253}
4254
4255/* BGP peer configuration display function. */
4256void
4257bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4258 struct peer *peer, afi_t afi, safi_t safi)
4259{
4260 struct bgp_filter *filter;
4261 struct peer *g_peer = NULL;
4262 char buf[SU_ADDRSTRLEN];
4263 char *addr;
4264
4265 filter = &peer->filter[afi][safi];
4266 addr = peer->host;
4267 if (peer_group_active (peer))
4268 g_peer = peer->group->conf;
4269
4270 /************************************
4271 ****** Global to the neighbor ******
4272 ************************************/
4273 if (afi == AFI_IP && safi == SAFI_UNICAST)
4274 {
4275 /* remote-as. */
4276 if (! peer_group_active (peer))
4277 {
4278 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4279 vty_out (vty, " neighbor %s peer-group%s", addr,
4280 VTY_NEWLINE);
4281 if (peer->as)
4282 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4283 VTY_NEWLINE);
4284 }
4285 else
4286 {
4287 if (! g_peer->as)
4288 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4289 VTY_NEWLINE);
4290 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4291 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4292 peer->group->name, VTY_NEWLINE);
4293 }
4294
4295 /* local-as. */
4296 if (peer->change_local_as)
4297 if (! peer_group_active (peer))
4298 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4299 peer->change_local_as,
4300 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4301 " no-prepend" : "", VTY_NEWLINE);
4302
4303 /* Description. */
4304 if (peer->desc)
4305 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4306 VTY_NEWLINE);
4307
4308 /* Shutdown. */
4309 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4310 if (! peer_group_active (peer) ||
4311 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4312 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4313
4314 /* BGP port. */
4315 if (peer->port != BGP_PORT_DEFAULT)
4316 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4317 VTY_NEWLINE);
4318
4319 /* Local interface name. */
4320 if (peer->ifname)
4321 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4322 VTY_NEWLINE);
4323
4324 /* Passive. */
4325 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4326 if (! peer_group_active (peer) ||
4327 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4328 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4329
4330 /* EBGP multihop. */
4331 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4332 if (! peer_group_active (peer) ||
4333 g_peer->ttl != peer->ttl)
4334 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4335 VTY_NEWLINE);
4336
hasso6ffd2072005-02-02 14:50:11 +00004337 /* disable-connected-check. */
4338 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004339 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004340 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4341 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004342
4343 /* Update-source. */
4344 if (peer->update_if)
4345 if (! peer_group_active (peer) || ! g_peer->update_if
4346 || strcmp (g_peer->update_if, peer->update_if) != 0)
4347 vty_out (vty, " neighbor %s update-source %s%s", addr,
4348 peer->update_if, VTY_NEWLINE);
4349 if (peer->update_source)
4350 if (! peer_group_active (peer) || ! g_peer->update_source
4351 || sockunion_cmp (g_peer->update_source,
4352 peer->update_source) != 0)
4353 vty_out (vty, " neighbor %s update-source %s%s", addr,
4354 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4355 VTY_NEWLINE);
4356
paul718e3742002-12-13 20:15:29 +00004357 /* advertisement-interval */
4358 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4359 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4360 addr, peer->v_routeadv, VTY_NEWLINE);
4361
4362 /* timers. */
4363 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4364 && ! peer_group_active (peer))
4365 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4366 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4367
4368 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4369 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4370 peer->connect, VTY_NEWLINE);
4371
4372 /* Default weight. */
4373 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4374 if (! peer_group_active (peer) ||
4375 g_peer->weight != peer->weight)
4376 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4377 VTY_NEWLINE);
4378
paul718e3742002-12-13 20:15:29 +00004379 /* Dynamic capability. */
4380 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4381 if (! peer_group_active (peer) ||
4382 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4383 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4384 VTY_NEWLINE);
4385
4386 /* dont capability negotiation. */
4387 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4388 if (! peer_group_active (peer) ||
4389 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4390 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4391 VTY_NEWLINE);
4392
4393 /* override capability negotiation. */
4394 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4395 if (! peer_group_active (peer) ||
4396 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4397 vty_out (vty, " neighbor %s override-capability%s", addr,
4398 VTY_NEWLINE);
4399
4400 /* strict capability negotiation. */
4401 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4402 if (! peer_group_active (peer) ||
4403 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4404 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4405 VTY_NEWLINE);
4406
4407 if (! peer_group_active (peer))
4408 {
4409 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4410 {
4411 if (peer->afc[AFI_IP][SAFI_UNICAST])
4412 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4413 }
4414 else
4415 {
4416 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4417 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4418 }
4419 }
4420 }
4421
4422
4423 /************************************
4424 ****** Per AF to the neighbor ******
4425 ************************************/
4426
4427 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4428 {
4429 if (peer->af_group[afi][safi])
4430 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4431 peer->group->name, VTY_NEWLINE);
4432 else
4433 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4434 }
4435
4436 /* ORF capability. */
4437 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4438 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4439 if (! peer->af_group[afi][safi])
4440 {
4441 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4442
4443 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4444 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4445 vty_out (vty, " both");
4446 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4447 vty_out (vty, " send");
4448 else
4449 vty_out (vty, " receive");
4450 vty_out (vty, "%s", VTY_NEWLINE);
4451 }
4452
4453 /* Route reflector client. */
4454 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4455 && ! peer->af_group[afi][safi])
4456 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4457 VTY_NEWLINE);
4458
4459 /* Nexthop self. */
4460 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4461 && ! peer->af_group[afi][safi])
4462 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4463
4464 /* Remove private AS. */
4465 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4466 && ! peer->af_group[afi][safi])
4467 vty_out (vty, " neighbor %s remove-private-AS%s",
4468 addr, VTY_NEWLINE);
4469
4470 /* send-community print. */
4471 if (! peer->af_group[afi][safi])
4472 {
4473 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4474 {
4475 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4476 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4477 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4478 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4479 vty_out (vty, " neighbor %s send-community extended%s",
4480 addr, VTY_NEWLINE);
4481 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4482 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4483 }
4484 else
4485 {
4486 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4487 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4488 vty_out (vty, " no neighbor %s send-community both%s",
4489 addr, VTY_NEWLINE);
4490 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4491 vty_out (vty, " no neighbor %s send-community extended%s",
4492 addr, VTY_NEWLINE);
4493 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4494 vty_out (vty, " no neighbor %s send-community%s",
4495 addr, VTY_NEWLINE);
4496 }
4497 }
4498
4499 /* Default information */
4500 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4501 && ! peer->af_group[afi][safi])
4502 {
4503 vty_out (vty, " neighbor %s default-originate", addr);
4504 if (peer->default_rmap[afi][safi].name)
4505 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4506 vty_out (vty, "%s", VTY_NEWLINE);
4507 }
4508
4509 /* Soft reconfiguration inbound. */
4510 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4511 if (! peer->af_group[afi][safi] ||
4512 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4513 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4514 VTY_NEWLINE);
4515
4516 /* maximum-prefix. */
4517 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4518 if (! peer->af_group[afi][safi]
4519 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004520 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004521 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4522 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004523 {
hasso0a486e52005-02-01 20:57:17 +00004524 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4525 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4526 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4527 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4528 vty_out (vty, " warning-only");
4529 if (peer->pmax_restart[afi][safi])
4530 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4531 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004532 }
paul718e3742002-12-13 20:15:29 +00004533
4534 /* Route server client. */
4535 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4536 && ! peer->af_group[afi][safi])
4537 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4538
4539 /* Allow AS in. */
4540 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4541 if (! peer_group_active (peer)
4542 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4543 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4544 {
4545 if (peer->allowas_in[afi][safi] == 3)
4546 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4547 else
4548 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4549 peer->allowas_in[afi][safi], VTY_NEWLINE);
4550 }
4551
4552 /* Filter. */
4553 bgp_config_write_filter (vty, peer, afi, safi);
4554
4555 /* atribute-unchanged. */
4556 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4557 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4558 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4559 && ! peer->af_group[afi][safi])
4560 {
4561 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4562 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4563 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4564 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4565 else
4566 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4567 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4568 " as-path" : "",
4569 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4570 " next-hop" : "",
4571 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4572 " med" : "", VTY_NEWLINE);
4573 }
4574}
4575
4576/* Display "address-family" configuration header. */
4577void
4578bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4579 int *write)
4580{
4581 if (*write)
4582 return;
4583
4584 if (afi == AFI_IP && safi == SAFI_UNICAST)
4585 return;
4586
4587 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4588
4589 if (afi == AFI_IP)
4590 {
4591 if (safi == SAFI_MULTICAST)
4592 vty_out (vty, "ipv4 multicast");
4593 else if (safi == SAFI_MPLS_VPN)
4594 vty_out (vty, "vpnv4 unicast");
4595 }
4596 else if (afi == AFI_IP6)
4597 vty_out (vty, "ipv6");
4598
4599 vty_out (vty, "%s", VTY_NEWLINE);
4600
4601 *write = 1;
4602}
4603
4604/* Address family based peer configuration display. */
4605int
4606bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4607 safi_t safi)
4608{
4609 int write = 0;
4610 struct peer *peer;
4611 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004612 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004613
4614 bgp_config_write_network (vty, bgp, afi, safi, &write);
4615
4616 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4617
paul1eb8ef22005-04-07 07:30:20 +00004618 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004619 {
4620 if (group->conf->afc[afi][safi])
4621 {
4622 bgp_config_write_family_header (vty, afi, safi, &write);
4623 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4624 }
4625 }
paul1eb8ef22005-04-07 07:30:20 +00004626 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004627 {
4628 if (peer->afc[afi][safi])
4629 {
4630 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4631 {
4632 bgp_config_write_family_header (vty, afi, safi, &write);
4633 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4634 }
4635 }
4636 }
4637 if (write)
4638 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4639
4640 return write;
4641}
4642
4643int
4644bgp_config_write (struct vty *vty)
4645{
4646 int write = 0;
4647 struct bgp *bgp;
4648 struct peer_group *group;
4649 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004650 struct listnode *node, *nnode;
4651 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004652
4653 /* BGP Multiple instance. */
4654 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4655 {
4656 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4657 write++;
4658 }
4659
4660 /* BGP Config type. */
4661 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4662 {
4663 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4664 write++;
4665 }
4666
4667 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004668 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004669 {
4670 if (write)
4671 vty_out (vty, "!%s", VTY_NEWLINE);
4672
4673 /* Router bgp ASN */
4674 vty_out (vty, "router bgp %d", bgp->as);
4675
4676 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4677 {
4678 if (bgp->name)
4679 vty_out (vty, " view %s", bgp->name);
4680 }
4681 vty_out (vty, "%s", VTY_NEWLINE);
4682
4683 /* No Synchronization */
4684 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4685 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4686
4687 /* BGP fast-external-failover. */
4688 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4689 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4690
4691 /* BGP router ID. */
4692 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4693 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4694 VTY_NEWLINE);
4695
paul848973c2003-08-13 00:32:49 +00004696 /* BGP log-neighbor-changes. */
4697 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4698 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4699
paul718e3742002-12-13 20:15:29 +00004700 /* BGP configuration. */
4701 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4702 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4703
4704 /* BGP default ipv4-unicast. */
4705 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4706 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4707
4708 /* BGP default local-preference. */
4709 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4710 vty_out (vty, " bgp default local-preference %d%s",
4711 bgp->default_local_pref, VTY_NEWLINE);
4712
4713 /* BGP client-to-client reflection. */
4714 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4715 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4716
4717 /* BGP cluster ID. */
4718 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4719 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4720 VTY_NEWLINE);
4721
hassoe0701b72004-05-20 09:19:34 +00004722 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004723 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004724 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4725 VTY_NEWLINE);
4726
4727 /* Confederation peer */
4728 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004729 {
hassoe0701b72004-05-20 09:19:34 +00004730 int i;
paul718e3742002-12-13 20:15:29 +00004731
hassoe0701b72004-05-20 09:19:34 +00004732 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004733
hassoe0701b72004-05-20 09:19:34 +00004734 for (i = 0; i < bgp->confed_peers_cnt; i++)
4735 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004736
hassoe0701b72004-05-20 09:19:34 +00004737 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004738 }
4739
4740 /* BGP enforce-first-as. */
4741 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4742 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4743
4744 /* BGP deterministic-med. */
4745 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4746 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004747
4748 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004749 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4750 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4751 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004752 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4753 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4754
paul718e3742002-12-13 20:15:29 +00004755 /* BGP bestpath method. */
4756 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4757 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004758 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4759 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004760 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4761 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4762 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4763 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4764 {
4765 vty_out (vty, " bgp bestpath med");
4766 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4767 vty_out (vty, " confed");
4768 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4769 vty_out (vty, " missing-as-worst");
4770 vty_out (vty, "%s", VTY_NEWLINE);
4771 }
4772
4773 /* BGP network import check. */
4774 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4775 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4776
4777 /* BGP scan interval. */
4778 bgp_config_write_scan_time (vty);
4779
4780 /* BGP flag dampening. */
4781 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4782 BGP_CONFIG_DAMPENING))
4783 bgp_config_write_damp (vty);
4784
4785 /* BGP static route configuration. */
4786 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4787
4788 /* BGP redistribute configuration. */
4789 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4790
4791 /* BGP timers configuration. */
4792 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4793 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4794 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4795 bgp->default_holdtime, VTY_NEWLINE);
4796
4797 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004798 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004799 {
4800 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4801 }
4802
4803 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004804 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004805 {
4806 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4807 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4808 }
4809
4810 /* Distance configuration. */
4811 bgp_config_write_distance (vty, bgp);
4812
4813 /* No auto-summary */
4814 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4815 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4816
4817 /* IPv4 multicast configuration. */
4818 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4819
4820 /* IPv4 VPN configuration. */
4821 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4822
4823 /* IPv6 unicast configuration. */
4824 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4825
4826 write++;
4827 }
4828 return write;
4829}
4830
4831void
4832bgp_master_init ()
4833{
4834 memset (&bgp_master, 0, sizeof (struct bgp_master));
4835
4836 bm = &bgp_master;
4837 bm->bgp = list_new ();
4838 bm->port = BGP_PORT_DEFAULT;
4839 bm->master = thread_master_create ();
4840 bm->start_time = time (NULL);
4841}
4842
4843void
4844bgp_init ()
4845{
4846 void bgp_zebra_init ();
4847 void bgp_route_map_init ();
4848 void bgp_filter_init ();
4849
4850 /* BGP VTY commands installation. */
4851 bgp_vty_init ();
4852
4853 /* Create BGP server socket. */
4854 bgp_socket (NULL, bm->port);
4855
4856 /* Init zebra. */
4857 bgp_zebra_init ();
4858
4859 /* BGP inits. */
4860 bgp_attr_init ();
4861 bgp_debug_init ();
4862 bgp_dump_init ();
4863 bgp_route_init ();
4864 bgp_route_map_init ();
4865 bgp_scan_init ();
4866 bgp_mplsvpn_init ();
4867
4868 /* Access list initialize. */
4869 access_list_init ();
4870 access_list_add_hook (peer_distribute_update);
4871 access_list_delete_hook (peer_distribute_update);
4872
4873 /* Filter list initialize. */
4874 bgp_filter_init ();
4875 as_list_add_hook (peer_aslist_update);
4876 as_list_delete_hook (peer_aslist_update);
4877
4878 /* Prefix list initialize.*/
4879 prefix_list_init ();
4880 prefix_list_add_hook (peer_prefix_list_update);
4881 prefix_list_delete_hook (peer_prefix_list_update);
4882
4883 /* Community list initialize. */
4884 bgp_clist = community_list_init ();
4885
4886#ifdef HAVE_SNMP
4887 bgp_snmp_init ();
4888#endif /* HAVE_SNMP */
4889}
paul545acaf2004-04-20 15:13:15 +00004890
4891void
4892bgp_terminate ()
4893{
paul545acaf2004-04-20 15:13:15 +00004894 struct bgp *bgp;
4895 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004896 struct listnode *node, *nnode;
4897 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004898
paul1eb8ef22005-04-07 07:30:20 +00004899 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4900 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00004901 if (peer->status == Established)
4902 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4903 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00004904
paul545acaf2004-04-20 15:13:15 +00004905 bgp_cleanup_routes ();
4906}
4907