blob: 8ed598d282cd3431594e2fbddd0baa18693220d1 [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"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
hasso18a6dce2004-10-03 18:18:34 +000067extern struct in_addr router_id_zebra;
68
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000088 }
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;
paul718e3742002-12-13 20:15:29 +0000107 }
108 return 0;
109}
110
111int
112bgp_option_check (int flag)
113{
114 return CHECK_FLAG (bm->options, flag);
115}
116
117/* BGP flag manipulation. */
118int
119bgp_flag_set (struct bgp *bgp, int flag)
120{
121 SET_FLAG (bgp->flags, flag);
122 return 0;
123}
124
125int
126bgp_flag_unset (struct bgp *bgp, int flag)
127{
128 UNSET_FLAG (bgp->flags, flag);
129 return 0;
130}
131
132int
133bgp_flag_check (struct bgp *bgp, int flag)
134{
135 return CHECK_FLAG (bgp->flags, flag);
136}
137
138/* Internal function to set BGP structure configureation flag. */
139static void
140bgp_config_set (struct bgp *bgp, int config)
141{
142 SET_FLAG (bgp->config, config);
143}
144
145static void
146bgp_config_unset (struct bgp *bgp, int config)
147{
148 UNSET_FLAG (bgp->config, config);
149}
150
151static int
152bgp_config_check (struct bgp *bgp, int config)
153{
154 return CHECK_FLAG (bgp->config, config);
155}
156
157/* Set BGP router identifier. */
158int
159bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
160{
161 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000163
164 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
165 && IPV4_ADDR_SAME (&bgp->router_id, id))
166 return 0;
167
168 IPV4_ADDR_COPY (&bgp->router_id, id);
169 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
170
171 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000173 {
174 IPV4_ADDR_COPY (&peer->local_id, id);
175
176 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000177 {
178 peer->last_reset = PEER_DOWN_RID_CHANGE;
179 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
180 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
181 }
paul718e3742002-12-13 20:15:29 +0000182 }
183 return 0;
184}
185
paul718e3742002-12-13 20:15:29 +0000186/* BGP's cluster-id control. */
187int
188bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
189{
190 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000191 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000192
193 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
194 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
195 return 0;
196
197 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
198 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
199
200 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000202 {
203 if (peer_sort (peer) != BGP_PEER_IBGP)
204 continue;
205
206 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000207 {
208 peer->last_reset = PEER_DOWN_CLID_CHANGE;
209 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
210 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
211 }
paul718e3742002-12-13 20:15:29 +0000212 }
213 return 0;
214}
215
216int
217bgp_cluster_id_unset (struct bgp *bgp)
218{
219 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000220 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000221
222 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
223 return 0;
224
225 bgp->cluster_id.s_addr = 0;
226 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
227
228 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000229 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000230 {
231 if (peer_sort (peer) != BGP_PEER_IBGP)
232 continue;
233
234 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000235 {
236 peer->last_reset = PEER_DOWN_CLID_CHANGE;
237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
239 }
paul718e3742002-12-13 20:15:29 +0000240 }
241 return 0;
242}
243
244/* BGP timer configuration. */
245int
246bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
247{
248 bgp->default_keepalive = (keepalive < holdtime / 3
249 ? keepalive : holdtime / 3);
250 bgp->default_holdtime = holdtime;
251
252 return 0;
253}
254
255int
256bgp_timers_unset (struct bgp *bgp)
257{
258 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
259 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
260
261 return 0;
262}
263
264/* BGP confederation configuration. */
265int
266bgp_confederation_id_set (struct bgp *bgp, as_t as)
267{
268 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000269 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000270 int already_confed;
271
272 if (as == 0)
273 return BGP_ERR_INVALID_AS;
274
275 /* Remember - were we doing confederation before? */
276 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
277 bgp->confed_id = as;
278 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
279
280 /* If we were doing confederation already, this is just an external
281 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
282 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000283 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000284 {
285 /* We're looking for peers who's AS is not local or part of our
286 confederation. */
287 if (already_confed)
288 {
289 if (peer_sort (peer) == BGP_PEER_EBGP)
290 {
291 peer->local_as = as;
292 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000293 {
294 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
295 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
297 }
298
paul718e3742002-12-13 20:15:29 +0000299 else
300 BGP_EVENT_ADD (peer, BGP_Stop);
301 }
302 }
303 else
304 {
305 /* Not doign confederation before, so reset every non-local
306 session */
307 if (peer_sort (peer) != BGP_PEER_IBGP)
308 {
309 /* Reset the local_as to be our EBGP one */
310 if (peer_sort (peer) == BGP_PEER_EBGP)
311 peer->local_as = as;
312 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000313 {
314 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
315 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
316 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
317 }
paul718e3742002-12-13 20:15:29 +0000318 else
319 BGP_EVENT_ADD (peer, BGP_Stop);
320 }
321 }
322 }
323 return 0;
324}
325
326int
327bgp_confederation_id_unset (struct bgp *bgp)
328{
329 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000331
332 bgp->confed_id = 0;
333 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
334
paul1eb8ef22005-04-07 07:30:20 +0000335 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000336 {
337 /* We're looking for peers who's AS is not local */
338 if (peer_sort (peer) != BGP_PEER_IBGP)
339 {
340 peer->local_as = bgp->as;
341 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000342 {
343 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
344 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
345 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
346 }
347
paul718e3742002-12-13 20:15:29 +0000348 else
349 BGP_EVENT_ADD (peer, BGP_Stop);
350 }
351 }
352 return 0;
353}
354
355/* Is an AS part of the confed or not? */
356int
357bgp_confederation_peers_check (struct bgp *bgp, as_t as)
358{
359 int i;
360
361 if (! bgp)
362 return 0;
363
364 for (i = 0; i < bgp->confed_peers_cnt; i++)
365 if (bgp->confed_peers[i] == as)
366 return 1;
367
368 return 0;
369}
370
371/* Add an AS to the confederation set. */
372int
373bgp_confederation_peers_add (struct bgp *bgp, as_t as)
374{
375 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000376 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000377
378 if (! bgp)
379 return BGP_ERR_INVALID_BGP;
380
381 if (bgp->as == as)
382 return BGP_ERR_INVALID_AS;
383
384 if (bgp_confederation_peers_check (bgp, as))
385 return -1;
386
387 if (bgp->confed_peers)
388 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
389 bgp->confed_peers,
390 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
391 else
392 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
393 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
394
395 bgp->confed_peers[bgp->confed_peers_cnt] = as;
396 bgp->confed_peers_cnt++;
397
398 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
399 {
paul1eb8ef22005-04-07 07:30:20 +0000400 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000401 {
402 if (peer->as == as)
403 {
404 peer->local_as = bgp->as;
405 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000406 {
407 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
408 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
409 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
410 }
paul718e3742002-12-13 20:15:29 +0000411 else
412 BGP_EVENT_ADD (peer, BGP_Stop);
413 }
414 }
415 }
416 return 0;
417}
418
419/* Delete an AS from the confederation set. */
420int
421bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
422{
423 int i;
424 int j;
425 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000426 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000427
428 if (! bgp)
429 return -1;
430
431 if (! bgp_confederation_peers_check (bgp, as))
432 return -1;
433
434 for (i = 0; i < bgp->confed_peers_cnt; i++)
435 if (bgp->confed_peers[i] == as)
436 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
437 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
438
439 bgp->confed_peers_cnt--;
440
441 if (bgp->confed_peers_cnt == 0)
442 {
443 if (bgp->confed_peers)
444 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
445 bgp->confed_peers = NULL;
446 }
447 else
448 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
449 bgp->confed_peers,
450 bgp->confed_peers_cnt * sizeof (as_t));
451
452 /* Now reset any peer who's remote AS has just been removed from the
453 CONFED */
454 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
455 {
paul1eb8ef22005-04-07 07:30:20 +0000456 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000457 {
458 if (peer->as == as)
459 {
460 peer->local_as = bgp->confed_id;
461 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000462 {
463 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
466 }
paul718e3742002-12-13 20:15:29 +0000467 else
468 BGP_EVENT_ADD (peer, BGP_Stop);
469 }
470 }
471 }
472
473 return 0;
474}
475
476/* Local preference configuration. */
477int
478bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
479{
480 if (! bgp)
481 return -1;
482
paul718e3742002-12-13 20:15:29 +0000483 bgp->default_local_pref = local_pref;
484
485 return 0;
486}
487
488int
489bgp_default_local_preference_unset (struct bgp *bgp)
490{
491 if (! bgp)
492 return -1;
493
paul718e3742002-12-13 20:15:29 +0000494 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
495
496 return 0;
497}
498
paulfee0f4c2004-09-13 05:12:46 +0000499/* If peer is RSERVER_CLIENT in at least one address family and is not member
500 of a peer_group for that family, return 1.
501 Used to check wether the peer is included in list bgp->rsclient. */
502int
503peer_rsclient_active (struct peer *peer)
504{
505 int i;
506 int j;
507
508 for (i=AFI_IP; i < AFI_MAX; i++)
509 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
510 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
511 && ! peer->af_group[i][j])
512 return 1;
513 return 0;
514}
515
pauleb821182004-05-01 08:44:08 +0000516/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000517static int
518peer_cmp (struct peer *p1, struct peer *p2)
519{
pauleb821182004-05-01 08:44:08 +0000520 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000521}
522
523int
524peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
525{
526 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
527}
528
529/* Reset all address family specific configuration. */
530static void
531peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
532{
533 int i;
534 struct bgp_filter *filter;
535 char orf_name[BUFSIZ];
536
537 filter = &peer->filter[afi][safi];
538
539 /* Clear neighbor filter and route-map */
540 for (i = FILTER_IN; i < FILTER_MAX; i++)
541 {
542 if (filter->dlist[i].name)
543 {
544 free (filter->dlist[i].name);
545 filter->dlist[i].name = NULL;
546 }
547 if (filter->plist[i].name)
548 {
549 free (filter->plist[i].name);
550 filter->plist[i].name = NULL;
551 }
552 if (filter->aslist[i].name)
553 {
554 free (filter->aslist[i].name);
555 filter->aslist[i].name = NULL;
556 }
paulfee0f4c2004-09-13 05:12:46 +0000557 }
558 for (i = RMAP_IN; i < RMAP_MAX; i++)
559 {
paul718e3742002-12-13 20:15:29 +0000560 if (filter->map[i].name)
561 {
562 free (filter->map[i].name);
563 filter->map[i].name = NULL;
564 }
565 }
566
567 /* Clear unsuppress map. */
568 if (filter->usmap.name)
569 free (filter->usmap.name);
570 filter->usmap.name = NULL;
571 filter->usmap.map = NULL;
572
573 /* Clear neighbor's all address family flags. */
574 peer->af_flags[afi][safi] = 0;
575
576 /* Clear neighbor's all address family sflags. */
577 peer->af_sflags[afi][safi] = 0;
578
579 /* Clear neighbor's all address family capabilities. */
580 peer->af_cap[afi][safi] = 0;
581
582 /* Clear ORF info */
583 peer->orf_plist[afi][safi] = NULL;
584 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
585 prefix_bgp_orf_remove_all (orf_name);
586
587 /* Set default neighbor send-community. */
588 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
589 {
590 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
592 }
593
594 /* Clear neighbor default_originate_rmap */
595 if (peer->default_rmap[afi][safi].name)
596 free (peer->default_rmap[afi][safi].name);
597 peer->default_rmap[afi][safi].name = NULL;
598 peer->default_rmap[afi][safi].map = NULL;
599
600 /* Clear neighbor maximum-prefix */
601 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000602 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000603}
604
605/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000606static void
paul718e3742002-12-13 20:15:29 +0000607peer_global_config_reset (struct peer *peer)
608{
609 peer->weight = 0;
610 peer->change_local_as = 0;
611 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
612 if (peer->update_source)
613 {
614 sockunion_free (peer->update_source);
615 peer->update_source = NULL;
616 }
617 if (peer->update_if)
618 {
619 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
620 peer->update_if = NULL;
621 }
622
623 if (peer_sort (peer) == BGP_PEER_IBGP)
624 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
625 else
626 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
627
628 peer->flags = 0;
629 peer->config = 0;
630 peer->holdtime = 0;
631 peer->keepalive = 0;
632 peer->connect = 0;
633 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
634}
635
636/* Check peer's AS number and determin is this peer IBGP or EBGP */
637int
638peer_sort (struct peer *peer)
639{
640 struct bgp *bgp;
641
642 bgp = peer->bgp;
643
644 /* Peer-group */
645 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
646 {
647 if (peer->as)
648 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
649 else
650 {
651 struct peer *peer1;
652 peer1 = listnode_head (peer->group->peer);
653 if (peer1)
654 return (peer1->local_as == peer1->as
655 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
656 }
657 return BGP_PEER_INTERNAL;
658 }
659
660 /* Normal peer */
661 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
662 {
663 if (peer->local_as == 0)
664 return BGP_PEER_INTERNAL;
665
666 if (peer->local_as == peer->as)
667 {
668 if (peer->local_as == bgp->confed_id)
669 return BGP_PEER_EBGP;
670 else
671 return BGP_PEER_IBGP;
672 }
673
674 if (bgp_confederation_peers_check (bgp, peer->as))
675 return BGP_PEER_CONFED;
676
677 return BGP_PEER_EBGP;
678 }
679 else
680 {
681 return (peer->local_as == 0
682 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
683 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
684 }
685}
686
paul200df112005-06-01 11:17:05 +0000687static inline void
688peer_free (struct peer *peer)
689{
690 if (peer->desc)
691 XFREE (MTYPE_PEER_DESC, peer->desc);
692
693 /* Free allocated host character. */
694 if (peer->host)
695 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
696
697 /* Update source configuration. */
698 if (peer->update_source)
699 sockunion_free (peer->update_source);
700
701 if (peer->update_if)
702 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000703
704 if (peer->clear_node_queue)
705 work_queue_free (peer->clear_node_queue);
706
paul200df112005-06-01 11:17:05 +0000707 memset (peer, 0, sizeof (struct peer));
708
709 XFREE (MTYPE_BGP_PEER, peer);
710}
711
712/* increase reference count on a struct peer */
713struct peer *
714peer_lock (struct peer *peer)
715{
716 assert (peer && (peer->lock >= 0));
717
718 peer->lock++;
719
720 return peer;
721}
722
723/* decrease reference count on a struct peer
724 * struct peer is freed and NULL returned if last reference
725 */
726struct peer *
727peer_unlock (struct peer *peer)
728{
729 assert (peer && (peer->lock > 0));
730
731 peer->lock--;
732
733 if (peer->lock == 0)
734 {
735#if 0
736 zlog_debug ("unlocked and freeing");
737 zlog_backtrace (LOG_DEBUG);
738#endif
739 peer_free (peer);
740 return NULL;
741 }
742
743#if 0
744 if (peer->lock == 1)
745 {
746 zlog_debug ("unlocked to 1");
747 zlog_backtrace (LOG_DEBUG);
748 }
749#endif
750
751 return peer;
752}
753
754/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000755static struct peer *
756peer_new ()
757{
758 afi_t afi;
759 safi_t safi;
760 struct peer *peer;
761 struct servent *sp;
762
763 /* Allocate new peer. */
764 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
765 memset (peer, 0, sizeof (struct peer));
766
767 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000768 peer->fd = -1;
paul200df112005-06-01 11:17:05 +0000769 peer->lock = 1;
paul718e3742002-12-13 20:15:29 +0000770 peer->v_start = BGP_INIT_START_TIMER;
771 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
772 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
773 peer->status = Idle;
774 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000775 peer->weight = 0;
776
777 /* Set default flags. */
778 for (afi = AFI_IP; afi < AFI_MAX; afi++)
779 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
780 {
781 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
782 {
783 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
784 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
785 }
786 peer->orf_plist[afi][safi] = NULL;
787 }
788 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
789
790 /* Create buffers. */
791 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
792 peer->obuf = stream_fifo_new ();
793 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
794
795 bgp_sync_init (peer);
796
797 /* Get service port number. */
798 sp = getservbyname ("bgp", "tcp");
799 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
800
801 return peer;
802}
803
804/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000805static struct peer *
paul718e3742002-12-13 20:15:29 +0000806peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
807 as_t remote_as, afi_t afi, safi_t safi)
808{
809 int active;
810 struct peer *peer;
811 char buf[SU_ADDRSTRLEN];
812
813 peer = peer_new ();
814 peer->bgp = bgp;
815 peer->su = *su;
816 peer->local_as = local_as;
817 peer->as = remote_as;
818 peer->local_id = bgp->router_id;
819 peer->v_holdtime = bgp->default_holdtime;
820 peer->v_keepalive = bgp->default_keepalive;
821 if (peer_sort (peer) == BGP_PEER_IBGP)
822 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
823 else
824 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000825
826 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000827 listnode_add_sort (bgp->peer, peer);
828
829 active = peer_active (peer);
830
831 if (afi && safi)
832 peer->afc[afi][safi] = 1;
833
834 /* Last read time set */
835 peer->readtime = time (NULL);
836
paul848973c2003-08-13 00:32:49 +0000837 /* Last reset time set */
838 peer->resettime = time (NULL);
839
paul718e3742002-12-13 20:15:29 +0000840 /* Default TTL set. */
841 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
842
843 /* Make peer's address string. */
844 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000845 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000846
847 /* Set up peer's events and timers. */
848 if (! active && peer_active (peer))
849 bgp_timer_set (peer);
850
851 return peer;
852}
853
pauleb821182004-05-01 08:44:08 +0000854/* Make accept BGP peer. Called from bgp_accept (). */
855struct peer *
856peer_create_accept (struct bgp *bgp)
857{
858 struct peer *peer;
859
860 peer = peer_new ();
861 peer->bgp = bgp;
paul200df112005-06-01 11:17:05 +0000862
863 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000864 listnode_add_sort (bgp->peer, peer);
865
866 return peer;
867}
868
paul718e3742002-12-13 20:15:29 +0000869/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000870static void
paul718e3742002-12-13 20:15:29 +0000871peer_as_change (struct peer *peer, as_t as)
872{
873 int type;
874
875 /* Stop peer. */
876 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
877 {
878 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000879 {
880 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
881 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
882 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
883 }
paul718e3742002-12-13 20:15:29 +0000884 else
885 BGP_EVENT_ADD (peer, BGP_Stop);
886 }
887 type = peer_sort (peer);
888 peer->as = as;
889
paul848973c2003-08-13 00:32:49 +0000890 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
891 && ! bgp_confederation_peers_check (peer->bgp, as)
892 && peer->bgp->as != as)
893 peer->local_as = peer->bgp->confed_id;
894 else
895 peer->local_as = peer->bgp->as;
896
paul718e3742002-12-13 20:15:29 +0000897 /* Advertisement-interval reset */
898 if (peer_sort (peer) == BGP_PEER_IBGP)
899 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
900 else
901 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
902
903 /* TTL reset */
904 if (peer_sort (peer) == BGP_PEER_IBGP)
905 peer->ttl = 255;
906 else if (type == BGP_PEER_IBGP)
907 peer->ttl = 1;
908
909 /* reflector-client reset */
910 if (peer_sort (peer) != BGP_PEER_IBGP)
911 {
912 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
913 PEER_FLAG_REFLECTOR_CLIENT);
914 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
915 PEER_FLAG_REFLECTOR_CLIENT);
916 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
917 PEER_FLAG_REFLECTOR_CLIENT);
918 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
919 PEER_FLAG_REFLECTOR_CLIENT);
920 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
921 PEER_FLAG_REFLECTOR_CLIENT);
922 }
923
924 /* local-as reset */
925 if (peer_sort (peer) != BGP_PEER_EBGP)
926 {
927 peer->change_local_as = 0;
928 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
929 }
930}
931
932/* If peer does not exist, create new one. If peer already exists,
933 set AS number to the peer. */
934int
935peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
936 afi_t afi, safi_t safi)
937{
938 struct peer *peer;
939 as_t local_as;
940
941 peer = peer_lookup (bgp, su);
942
943 if (peer)
944 {
945 /* When this peer is a member of peer-group. */
946 if (peer->group)
947 {
948 if (peer->group->conf->as)
949 {
950 /* Return peer group's AS number. */
951 *as = peer->group->conf->as;
952 return BGP_ERR_PEER_GROUP_MEMBER;
953 }
954 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
955 {
956 if (bgp->as != *as)
957 {
958 *as = peer->as;
959 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
960 }
961 }
962 else
963 {
964 if (bgp->as == *as)
965 {
966 *as = peer->as;
967 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
968 }
969 }
970 }
971
972 /* Existing peer's AS number change. */
973 if (peer->as != *as)
974 peer_as_change (peer, *as);
975 }
976 else
977 {
978
979 /* If the peer is not part of our confederation, and its not an
980 iBGP peer then spoof the source AS */
981 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
982 && ! bgp_confederation_peers_check (bgp, *as)
983 && bgp->as != *as)
984 local_as = bgp->confed_id;
985 else
986 local_as = bgp->as;
987
988 /* If this is IPv4 unicast configuration and "no bgp default
989 ipv4-unicast" is specified. */
990
991 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
992 && afi == AFI_IP && safi == SAFI_UNICAST)
993 peer = peer_create (su, bgp, local_as, *as, 0, 0);
994 else
995 peer = peer_create (su, bgp, local_as, *as, afi, safi);
996 }
997
998 return 0;
999}
1000
1001/* Activate the peer or peer group for specified AFI and SAFI. */
1002int
1003peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1004{
1005 int active;
1006
1007 if (peer->afc[afi][safi])
1008 return 0;
1009
1010 /* Activate the address family configuration. */
1011 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1012 peer->afc[afi][safi] = 1;
1013 else
1014 {
1015 active = peer_active (peer);
1016
1017 peer->afc[afi][safi] = 1;
1018
1019 if (! active && peer_active (peer))
1020 bgp_timer_set (peer);
1021 else
1022 {
1023 if (peer->status == Established)
1024 {
1025 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1026 {
1027 peer->afc_adv[afi][safi] = 1;
1028 bgp_capability_send (peer, afi, safi,
1029 CAPABILITY_CODE_MP,
1030 CAPABILITY_ACTION_SET);
1031 if (peer->afc_recv[afi][safi])
1032 {
1033 peer->afc_nego[afi][safi] = 1;
1034 bgp_announce_route (peer, afi, safi);
1035 }
1036 }
1037 else
hassoe0701b72004-05-20 09:19:34 +00001038 {
1039 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1040 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1041 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1042 }
paul718e3742002-12-13 20:15:29 +00001043 }
1044 }
1045 }
1046 return 0;
1047}
1048
1049int
1050peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1051{
1052 struct peer_group *group;
1053 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001054 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001055
1056 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1057 {
1058 group = peer->group;
1059
paul1eb8ef22005-04-07 07:30:20 +00001060 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001061 {
1062 if (peer1->af_group[afi][safi])
1063 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1064 }
1065 }
1066 else
1067 {
1068 if (peer->af_group[afi][safi])
1069 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1070 }
1071
1072 if (! peer->afc[afi][safi])
1073 return 0;
1074
1075 /* De-activate the address family configuration. */
1076 peer->afc[afi][safi] = 0;
1077 peer_af_flag_reset (peer, afi, safi);
1078
1079 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1080 {
1081 if (peer->status == Established)
1082 {
1083 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1084 {
1085 peer->afc_adv[afi][safi] = 0;
1086 peer->afc_nego[afi][safi] = 0;
1087
1088 if (peer_active_nego (peer))
1089 {
1090 bgp_capability_send (peer, afi, safi,
1091 CAPABILITY_CODE_MP,
1092 CAPABILITY_ACTION_UNSET);
1093 bgp_clear_route (peer, afi, safi);
1094 peer->pcount[afi][safi] = 0;
1095 }
1096 else
hassoe0701b72004-05-20 09:19:34 +00001097 {
1098 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1099 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1100 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1101 }
paul718e3742002-12-13 20:15:29 +00001102 }
1103 else
hassoe0701b72004-05-20 09:19:34 +00001104 {
1105 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1106 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1107 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1108 }
paul718e3742002-12-13 20:15:29 +00001109 }
1110 }
1111 return 0;
1112}
1113
hasso93406d82005-02-02 14:40:33 +00001114void
1115peer_nsf_stop (struct peer *peer)
1116{
1117 afi_t afi;
1118 safi_t safi;
1119
1120 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1121 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1122
1123 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1124 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1125 peer->nsf[afi][safi] = 0;
1126
1127 if (peer->t_gr_restart)
1128 {
1129 BGP_TIMER_OFF (peer->t_gr_restart);
1130 if (BGP_DEBUG (events, EVENTS))
1131 zlog_debug ("%s graceful restart timer stopped", peer->host);
1132 }
1133 if (peer->t_gr_stale)
1134 {
1135 BGP_TIMER_OFF (peer->t_gr_stale);
1136 if (BGP_DEBUG (events, EVENTS))
1137 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1138 }
1139 bgp_clear_route_all (peer);
1140}
1141
paul718e3742002-12-13 20:15:29 +00001142/* Delete peer from confguration. */
1143int
1144peer_delete (struct peer *peer)
1145{
1146 int i;
1147 afi_t afi;
1148 safi_t safi;
1149 struct bgp *bgp;
1150 struct bgp_filter *filter;
1151
1152 bgp = peer->bgp;
1153
hasso93406d82005-02-02 14:40:33 +00001154 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1155 peer_nsf_stop (peer);
1156
paul718e3742002-12-13 20:15:29 +00001157 /* If this peer belongs to peer group. Clearn up the
1158 relationship. */
1159 if (peer->group)
1160 {
paul200df112005-06-01 11:17:05 +00001161 peer = peer_unlock (peer); /* peer-group reference */
paul718e3742002-12-13 20:15:29 +00001162 listnode_delete (peer->group->peer, peer);
1163 peer->group = NULL;
1164 }
paul200df112005-06-01 11:17:05 +00001165
paul718e3742002-12-13 20:15:29 +00001166 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001167 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1168 * executed after peer structure is deleted.
1169 */
hassoe0701b72004-05-20 09:19:34 +00001170 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001171 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001172 bgp_fsm_change_status (peer, Idle); /* stops all timers */
1173
1174 /* Stop all timers - should already have been done in bgp_stop */
paul718e3742002-12-13 20:15:29 +00001175 BGP_TIMER_OFF (peer->t_start);
1176 BGP_TIMER_OFF (peer->t_connect);
1177 BGP_TIMER_OFF (peer->t_holdtime);
1178 BGP_TIMER_OFF (peer->t_keepalive);
1179 BGP_TIMER_OFF (peer->t_asorig);
1180 BGP_TIMER_OFF (peer->t_routeadv);
hasso0a486e52005-02-01 20:57:17 +00001181 BGP_TIMER_OFF (peer->t_pmax_restart);
hasso93406d82005-02-02 14:40:33 +00001182 BGP_TIMER_OFF (peer->t_gr_restart);
1183 BGP_TIMER_OFF (peer->t_gr_stale);
paul718e3742002-12-13 20:15:29 +00001184
1185 /* Delete from all peer list. */
1186 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001187 {
paul200df112005-06-01 11:17:05 +00001188 peer_unlock (peer); /* bgp peer list reference */
1189 listnode_delete (bgp->peer, peer);
1190
paulfee0f4c2004-09-13 05:12:46 +00001191 if (peer_rsclient_active (peer))
paul200df112005-06-01 11:17:05 +00001192 {
1193 peer_unlock (peer); /* rsclient list reference */
1194 listnode_delete (bgp->rsclient, peer);
1195 }
paulfee0f4c2004-09-13 05:12:46 +00001196 }
1197
1198 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1199 member of a peer_group. */
1200 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1201 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1202 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1203 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001204
paul200df112005-06-01 11:17:05 +00001205 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001206 if (peer->ibuf)
1207 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001208 if (peer->obuf)
1209 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001210 if (peer->work)
1211 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001212 peer->obuf = NULL;
1213 peer->work = peer->ibuf = NULL;
1214
paul718e3742002-12-13 20:15:29 +00001215 /* Local and remote addresses. */
1216 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001217 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001218 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001219 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001220 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001221
paul718e3742002-12-13 20:15:29 +00001222 bgp_sync_delete (peer);
1223
1224 /* Free filter related memory. */
1225 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1226 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1227 {
1228 filter = &peer->filter[afi][safi];
1229
1230 for (i = FILTER_IN; i < FILTER_MAX; i++)
1231 {
1232 if (filter->dlist[i].name)
1233 free (filter->dlist[i].name);
1234 if (filter->plist[i].name)
1235 free (filter->plist[i].name);
1236 if (filter->aslist[i].name)
1237 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001238
1239 filter->dlist[i].name = NULL;
1240 filter->plist[i].name = NULL;
1241 filter->aslist[i].name = NULL;
1242 }
1243 for (i = RMAP_IN; i < RMAP_MAX; i++)
1244 {
paul718e3742002-12-13 20:15:29 +00001245 if (filter->map[i].name)
1246 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001247 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001248 }
1249
1250 if (filter->usmap.name)
1251 free (filter->usmap.name);
1252
1253 if (peer->default_rmap[afi][safi].name)
1254 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001255
1256 filter->usmap.name = NULL;
1257 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001258 }
paul200df112005-06-01 11:17:05 +00001259
1260 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001261
1262 return 0;
1263}
1264
paul94f2b392005-06-28 12:44:16 +00001265static int
paul718e3742002-12-13 20:15:29 +00001266peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1267{
1268 return strcmp (g1->name, g2->name);
1269}
1270
1271/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001272static int
paul718e3742002-12-13 20:15:29 +00001273peer_group_active (struct peer *peer)
1274{
1275 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1276 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1277 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1278 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1279 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1280 return 1;
1281 return 0;
1282}
1283
1284/* Peer group cofiguration. */
1285static struct peer_group *
1286peer_group_new ()
1287{
1288 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1289 sizeof (struct peer_group));
1290}
1291
paul94f2b392005-06-28 12:44:16 +00001292static void
paul718e3742002-12-13 20:15:29 +00001293peer_group_free (struct peer_group *group)
1294{
1295 XFREE (MTYPE_PEER_GROUP, group);
1296}
1297
1298struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001299peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001300{
1301 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001302 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001303
paul1eb8ef22005-04-07 07:30:20 +00001304 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001305 {
1306 if (strcmp (group->name, name) == 0)
1307 return group;
1308 }
1309 return NULL;
1310}
1311
1312struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001313peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001314{
1315 struct peer_group *group;
1316
1317 group = peer_group_lookup (bgp, name);
1318 if (group)
1319 return group;
1320
1321 group = peer_group_new ();
1322 group->bgp = bgp;
1323 group->name = strdup (name);
1324 group->peer = list_new ();
1325 group->conf = peer_new ();
1326 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1327 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1328 group->conf->host = strdup (name);
1329 group->conf->bgp = bgp;
1330 group->conf->group = group;
1331 group->conf->as = 0;
1332 group->conf->ttl = 1;
1333 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1334 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1335 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1336 group->conf->keepalive = 0;
1337 group->conf->holdtime = 0;
1338 group->conf->connect = 0;
1339 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1340 listnode_add_sort (bgp->group, group);
1341
1342 return 0;
1343}
1344
paul94f2b392005-06-28 12:44:16 +00001345static void
paul718e3742002-12-13 20:15:29 +00001346peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1347 afi_t afi, safi_t safi)
1348{
1349 int in = FILTER_IN;
1350 int out = FILTER_OUT;
1351 struct peer *conf;
1352 struct bgp_filter *pfilter;
1353 struct bgp_filter *gfilter;
1354
1355 conf = group->conf;
1356 pfilter = &peer->filter[afi][safi];
1357 gfilter = &conf->filter[afi][safi];
1358
1359 /* remote-as */
1360 if (conf->as)
1361 peer->as = conf->as;
1362
1363 /* remote-as */
1364 if (conf->change_local_as)
1365 peer->change_local_as = conf->change_local_as;
1366
1367 /* TTL */
1368 peer->ttl = conf->ttl;
1369
1370 /* Weight */
1371 peer->weight = conf->weight;
1372
1373 /* peer flags apply */
1374 peer->flags = conf->flags;
1375 /* peer af_flags apply */
1376 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1377 /* peer config apply */
1378 peer->config = conf->config;
1379
1380 /* peer timers apply */
1381 peer->holdtime = conf->holdtime;
1382 peer->keepalive = conf->keepalive;
1383 peer->connect = conf->connect;
1384 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1385 peer->v_connect = conf->connect;
1386 else
1387 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1388
1389 /* advertisement-interval reset */
1390 if (peer_sort (peer) == BGP_PEER_IBGP)
1391 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1392 else
1393 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1394
1395 /* maximum-prefix */
1396 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001397 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001398 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001399
1400 /* allowas-in */
1401 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1402
paulfee0f4c2004-09-13 05:12:46 +00001403 /* route-server-client */
1404 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1405 {
1406 /* Make peer's RIB point to group's RIB. */
1407 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1408
1409 /* Import policy. */
1410 if (pfilter->map[RMAP_IMPORT].name)
1411 free (pfilter->map[RMAP_IMPORT].name);
1412 if (gfilter->map[RMAP_IMPORT].name)
1413 {
1414 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1415 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1416 }
1417 else
1418 {
1419 pfilter->map[RMAP_IMPORT].name = NULL;
1420 pfilter->map[RMAP_IMPORT].map = NULL;
1421 }
1422
1423 /* Export policy. */
1424 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1425 {
1426 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1427 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1428 }
1429 }
1430
paul718e3742002-12-13 20:15:29 +00001431 /* default-originate route-map */
1432 if (conf->default_rmap[afi][safi].name)
1433 {
1434 if (peer->default_rmap[afi][safi].name)
1435 free (peer->default_rmap[afi][safi].name);
1436 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1437 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1438 }
1439
1440 /* update-source apply */
1441 if (conf->update_source)
1442 {
1443 if (peer->update_source)
1444 sockunion_free (peer->update_source);
1445 if (peer->update_if)
1446 {
1447 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1448 peer->update_if = NULL;
1449 }
1450 peer->update_source = sockunion_dup (conf->update_source);
1451 }
1452 else if (conf->update_if)
1453 {
1454 if (peer->update_if)
1455 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1456 if (peer->update_source)
1457 {
1458 sockunion_free (peer->update_source);
1459 peer->update_source = NULL;
1460 }
1461 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1462 }
1463
1464 /* inbound filter apply */
1465 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1466 {
1467 if (pfilter->dlist[in].name)
1468 free (pfilter->dlist[in].name);
1469 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1470 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1471 }
1472 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1473 {
1474 if (pfilter->plist[in].name)
1475 free (pfilter->plist[in].name);
1476 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1477 pfilter->plist[in].plist = gfilter->plist[in].plist;
1478 }
1479 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1480 {
1481 if (pfilter->aslist[in].name)
1482 free (pfilter->aslist[in].name);
1483 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1484 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1485 }
paulfee0f4c2004-09-13 05:12:46 +00001486 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001487 {
paulfee0f4c2004-09-13 05:12:46 +00001488 if (pfilter->map[RMAP_IN].name)
1489 free (pfilter->map[RMAP_IN].name);
1490 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1491 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001492 }
1493
1494 /* outbound filter apply */
1495 if (gfilter->dlist[out].name)
1496 {
1497 if (pfilter->dlist[out].name)
1498 free (pfilter->dlist[out].name);
1499 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1500 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1501 }
1502 else
1503 {
1504 if (pfilter->dlist[out].name)
1505 free (pfilter->dlist[out].name);
1506 pfilter->dlist[out].name = NULL;
1507 pfilter->dlist[out].alist = NULL;
1508 }
1509 if (gfilter->plist[out].name)
1510 {
1511 if (pfilter->plist[out].name)
1512 free (pfilter->plist[out].name);
1513 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1514 pfilter->plist[out].plist = gfilter->plist[out].plist;
1515 }
1516 else
1517 {
1518 if (pfilter->plist[out].name)
1519 free (pfilter->plist[out].name);
1520 pfilter->plist[out].name = NULL;
1521 pfilter->plist[out].plist = NULL;
1522 }
1523 if (gfilter->aslist[out].name)
1524 {
1525 if (pfilter->aslist[out].name)
1526 free (pfilter->aslist[out].name);
1527 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1528 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1529 }
1530 else
1531 {
1532 if (pfilter->aslist[out].name)
1533 free (pfilter->aslist[out].name);
1534 pfilter->aslist[out].name = NULL;
1535 pfilter->aslist[out].aslist = NULL;
1536 }
paulfee0f4c2004-09-13 05:12:46 +00001537 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001538 {
paulfee0f4c2004-09-13 05:12:46 +00001539 if (pfilter->map[RMAP_OUT].name)
1540 free (pfilter->map[RMAP_OUT].name);
1541 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1542 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001543 }
1544 else
1545 {
paulfee0f4c2004-09-13 05:12:46 +00001546 if (pfilter->map[RMAP_OUT].name)
1547 free (pfilter->map[RMAP_OUT].name);
1548 pfilter->map[RMAP_OUT].name = NULL;
1549 pfilter->map[RMAP_OUT].map = NULL;
1550 }
1551
1552 /* RS-client's import/export route-maps. */
1553 if (gfilter->map[RMAP_IMPORT].name)
1554 {
1555 if (pfilter->map[RMAP_IMPORT].name)
1556 free (pfilter->map[RMAP_IMPORT].name);
1557 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1558 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1559 }
1560 else
1561 {
1562 if (pfilter->map[RMAP_IMPORT].name)
1563 free (pfilter->map[RMAP_IMPORT].name);
1564 pfilter->map[RMAP_IMPORT].name = NULL;
1565 pfilter->map[RMAP_IMPORT].map = NULL;
1566 }
1567 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1568 {
1569 if (pfilter->map[RMAP_EXPORT].name)
1570 free (pfilter->map[RMAP_EXPORT].name);
1571 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1572 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001573 }
1574
1575 if (gfilter->usmap.name)
1576 {
1577 if (pfilter->usmap.name)
1578 free (pfilter->usmap.name);
1579 pfilter->usmap.name = strdup (gfilter->usmap.name);
1580 pfilter->usmap.map = gfilter->usmap.map;
1581 }
1582 else
1583 {
1584 if (pfilter->usmap.name)
1585 free (pfilter->usmap.name);
1586 pfilter->usmap.name = NULL;
1587 pfilter->usmap.map = NULL;
1588 }
1589}
1590
1591/* Peer group's remote AS configuration. */
1592int
paulfd79ac92004-10-13 05:06:08 +00001593peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001594{
1595 struct peer_group *group;
1596 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001597 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001598
1599 group = peer_group_lookup (bgp, group_name);
1600 if (! group)
1601 return -1;
1602
1603 if (group->conf->as == *as)
1604 return 0;
1605
1606 /* When we setup peer-group AS number all peer group member's AS
1607 number must be updated to same number. */
1608 peer_as_change (group->conf, *as);
1609
paul1eb8ef22005-04-07 07:30:20 +00001610 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001611 {
1612 if (peer->as != *as)
1613 peer_as_change (peer, *as);
1614 }
1615
1616 return 0;
1617}
1618
1619int
1620peer_group_delete (struct peer_group *group)
1621{
1622 struct bgp *bgp;
1623 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001624 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001625
1626 bgp = group->bgp;
1627
paul1eb8ef22005-04-07 07:30:20 +00001628 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001629 {
1630 peer->group = NULL;
1631 peer_delete (peer);
1632 }
1633 list_delete (group->peer);
1634
1635 free (group->name);
1636 group->name = NULL;
1637
1638 group->conf->group = NULL;
1639 peer_delete (group->conf);
1640
1641 /* Delete from all peer_group list. */
1642 listnode_delete (bgp->group, group);
1643
1644 peer_group_free (group);
1645
1646 return 0;
1647}
1648
1649int
1650peer_group_remote_as_delete (struct peer_group *group)
1651{
1652 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001653 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001654
1655 if (! group->conf->as)
1656 return 0;
1657
paul1eb8ef22005-04-07 07:30:20 +00001658 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001659 {
1660 peer->group = NULL;
1661 peer_delete (peer);
1662 }
1663 list_delete_all_node (group->peer);
1664
1665 group->conf->as = 0;
1666
1667 return 0;
1668}
1669
1670/* Bind specified peer to peer group. */
1671int
1672peer_group_bind (struct bgp *bgp, union sockunion *su,
1673 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1674{
1675 struct peer *peer;
1676 int first_member = 0;
1677
1678 /* Check peer group's address family. */
1679 if (! group->conf->afc[afi][safi])
1680 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1681
1682 /* Lookup the peer. */
1683 peer = peer_lookup (bgp, su);
1684
1685 /* Create a new peer. */
1686 if (! peer)
1687 {
1688 if (! group->conf->as)
1689 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1690
1691 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1692 peer->group = group;
1693 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001694
1695 peer = peer_lock (peer); /* peer-group group->peer reference */
paul718e3742002-12-13 20:15:29 +00001696 listnode_add (group->peer, peer);
1697 peer_group2peer_config_copy (group, peer, afi, safi);
1698
1699 return 0;
1700 }
1701
1702 /* When the peer already belongs to peer group, check the consistency. */
1703 if (peer->af_group[afi][safi])
1704 {
1705 if (strcmp (peer->group->name, group->name) != 0)
1706 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1707
1708 return 0;
1709 }
1710
1711 /* Check current peer group configuration. */
1712 if (peer_group_active (peer)
1713 && strcmp (peer->group->name, group->name) != 0)
1714 return BGP_ERR_PEER_GROUP_MISMATCH;
1715
1716 if (! group->conf->as)
1717 {
1718 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1719 && peer_sort (group->conf) != peer_sort (peer))
1720 {
1721 if (as)
1722 *as = peer->as;
1723 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1724 }
1725
1726 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1727 first_member = 1;
1728 }
1729
1730 peer->af_group[afi][safi] = 1;
1731 peer->afc[afi][safi] = 1;
1732 if (! peer->group)
1733 {
1734 peer->group = group;
paul200df112005-06-01 11:17:05 +00001735
1736 peer = peer_lock (peer); /* peer-group group->peer reference */
paul718e3742002-12-13 20:15:29 +00001737 listnode_add (group->peer, peer);
1738 }
1739
1740 if (first_member)
1741 {
1742 /* Advertisement-interval reset */
1743 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1744 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1745 else
1746 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1747
1748 /* ebgp-multihop reset */
1749 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1750 group->conf->ttl = 255;
1751
1752 /* local-as reset */
1753 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1754 {
1755 group->conf->change_local_as = 0;
1756 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1757 }
1758 }
paulfee0f4c2004-09-13 05:12:46 +00001759
1760 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1761 {
1762 /* If it's not configured as RSERVER_CLIENT in any other address
1763 family, without being member of a peer_group, remove it from
1764 list bgp->rsclient.*/
1765 if (! peer_rsclient_active (peer))
paul200df112005-06-01 11:17:05 +00001766 {
1767 peer_unlock (peer); /* peer rsclient reference */
1768 listnode_delete (bgp->rsclient, peer);
1769 }
paulfee0f4c2004-09-13 05:12:46 +00001770
1771 bgp_table_finish (peer->rib[afi][safi]);
1772
1773 /* Import policy. */
1774 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1775 {
1776 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1777 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1778 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1779 }
1780
1781 /* Export policy. */
1782 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1783 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1784 {
1785 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1786 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1787 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1788 }
1789 }
1790
paul718e3742002-12-13 20:15:29 +00001791 peer_group2peer_config_copy (group, peer, afi, safi);
1792
1793 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001794 {
1795 peer->last_reset = PEER_DOWN_RMAP_BIND;
1796 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1797 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1798 }
paul718e3742002-12-13 20:15:29 +00001799 else
1800 BGP_EVENT_ADD (peer, BGP_Stop);
1801
1802 return 0;
1803}
1804
1805int
1806peer_group_unbind (struct bgp *bgp, struct peer *peer,
1807 struct peer_group *group, afi_t afi, safi_t safi)
1808{
1809 if (! peer->af_group[afi][safi])
1810 return 0;
1811
1812 if (group != peer->group)
1813 return BGP_ERR_PEER_GROUP_MISMATCH;
1814
1815 peer->af_group[afi][safi] = 0;
1816 peer->afc[afi][safi] = 0;
1817 peer_af_flag_reset (peer, afi, safi);
1818
paulfee0f4c2004-09-13 05:12:46 +00001819 if (peer->rib[afi][safi])
1820 peer->rib[afi][safi] = NULL;
1821
paul718e3742002-12-13 20:15:29 +00001822 if (! peer_group_active (peer))
1823 {
paul200df112005-06-01 11:17:05 +00001824 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001825 listnode_delete (group->peer, peer);
1826 peer->group = NULL;
1827 if (group->conf->as)
1828 {
1829 peer_delete (peer);
1830 return 0;
1831 }
1832 peer_global_config_reset (peer);
1833 }
1834
1835 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001836 {
1837 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1838 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1839 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1840 }
paul718e3742002-12-13 20:15:29 +00001841 else
1842 BGP_EVENT_ADD (peer, BGP_Stop);
1843
1844 return 0;
1845}
1846
1847/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001848static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001849bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001850{
1851 struct bgp *bgp;
1852 afi_t afi;
1853 safi_t safi;
1854
paul200df112005-06-01 11:17:05 +00001855 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1856 return NULL;
1857
paul718e3742002-12-13 20:15:29 +00001858 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001859 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001860
1861 bgp->peer = list_new ();
1862 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1863
1864 bgp->group = list_new ();
1865 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1866
paulfee0f4c2004-09-13 05:12:46 +00001867 bgp->rsclient = list_new ();
1868 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1869
paul718e3742002-12-13 20:15:29 +00001870 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1871 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1872 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001873 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1874 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1875 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001876 }
1877
1878 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1879 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1880 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001881 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1882 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001883
1884 bgp->as = *as;
1885
1886 if (name)
1887 bgp->name = strdup (name);
1888
1889 return bgp;
1890}
1891
1892/* Return first entry of BGP. */
1893struct bgp *
paul94f2b392005-06-28 12:44:16 +00001894bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001895{
1896 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001897 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001898 return NULL;
1899}
1900
1901/* Lookup BGP entry. */
1902struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001903bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001904{
1905 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001906 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001907
paul1eb8ef22005-04-07 07:30:20 +00001908 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001909 if (bgp->as == as
1910 && ((bgp->name == NULL && name == NULL)
1911 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1912 return bgp;
1913 return NULL;
1914}
1915
1916/* Lookup BGP structure by view name. */
1917struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001918bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001919{
1920 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001921 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001922
paul1eb8ef22005-04-07 07:30:20 +00001923 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001924 if ((bgp->name == NULL && name == NULL)
1925 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1926 return bgp;
1927 return NULL;
1928}
1929
1930/* Called from VTY commands. */
1931int
paulfd79ac92004-10-13 05:06:08 +00001932bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001933{
1934 struct bgp *bgp;
1935
1936 /* Multiple instance check. */
1937 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1938 {
1939 if (name)
1940 bgp = bgp_lookup_by_name (name);
1941 else
1942 bgp = bgp_get_default ();
1943
1944 /* Already exists. */
1945 if (bgp)
1946 {
1947 if (bgp->as != *as)
1948 {
1949 *as = bgp->as;
1950 return BGP_ERR_INSTANCE_MISMATCH;
1951 }
1952 *bgp_val = bgp;
1953 return 0;
1954 }
1955 }
1956 else
1957 {
1958 /* BGP instance name can not be specified for single instance. */
1959 if (name)
1960 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1961
1962 /* Get default BGP structure if exists. */
1963 bgp = bgp_get_default ();
1964
1965 if (bgp)
1966 {
1967 if (bgp->as != *as)
1968 {
1969 *as = bgp->as;
1970 return BGP_ERR_AS_MISMATCH;
1971 }
1972 *bgp_val = bgp;
1973 return 0;
1974 }
1975 }
1976
1977 bgp = bgp_create (as, name);
1978 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001979 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001980 *bgp_val = bgp;
1981
1982 return 0;
1983}
1984
1985/* Delete BGP instance. */
1986int
1987bgp_delete (struct bgp *bgp)
1988{
1989 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00001990 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001991 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001992 struct listnode *next;
1993 afi_t afi;
1994 safi_t safi;
1995 int i;
1996
1997 /* Delete static route. */
1998 bgp_static_delete (bgp);
1999
2000 /* Unset redistribution. */
2001 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2002 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2003 if (i != ZEBRA_ROUTE_BGP)
2004 bgp_redistribute_unset (bgp, afi, i);
2005
hassob6b7cff2005-05-26 08:29:07 +00002006 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2007 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002008 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002009
paul1eb8ef22005-04-07 07:30:20 +00002010 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2011 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002012 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002013
hasso54a6ed32005-05-26 22:12:33 +00002014 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2015 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002016 list_delete (bgp->rsclient);
2017
paul718e3742002-12-13 20:15:29 +00002018 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002019
paul718e3742002-12-13 20:15:29 +00002020 if (bgp->name)
2021 free (bgp->name);
2022
2023 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2024 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2025 {
2026 if (bgp->route[afi][safi])
2027 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2028 if (bgp->aggregate[afi][safi])
2029 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2030 if (bgp->rib[afi][safi])
2031 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2032 }
2033 XFREE (MTYPE_BGP, bgp);
2034
2035 return 0;
2036}
2037
2038struct peer *
2039peer_lookup (struct bgp *bgp, union sockunion *su)
2040{
2041 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002042 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002043
2044 if (! bgp)
2045 bgp = bgp_get_default ();
2046
2047 if (! bgp)
2048 return NULL;
2049
paul1eb8ef22005-04-07 07:30:20 +00002050 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002051 {
pauleb821182004-05-01 08:44:08 +00002052 if (sockunion_same (&peer->su, su)
2053 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2054 return peer;
paul718e3742002-12-13 20:15:29 +00002055 }
2056 return NULL;
2057}
2058
2059struct peer *
2060peer_lookup_with_open (union sockunion *su, as_t remote_as,
2061 struct in_addr *remote_id, int *as)
2062{
2063 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002064 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002065 struct bgp *bgp;
2066
2067 bgp = bgp_get_default ();
2068 if (! bgp)
2069 return NULL;
2070
paul1eb8ef22005-04-07 07:30:20 +00002071 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002072 {
pauleb821182004-05-01 08:44:08 +00002073 if (sockunion_same (&peer->su, su)
2074 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2075 {
2076 if (peer->as == remote_as
2077 && peer->remote_id.s_addr == remote_id->s_addr)
2078 return peer;
2079 if (peer->as == remote_as)
2080 *as = 1;
2081 }
paul718e3742002-12-13 20:15:29 +00002082 }
paul1eb8ef22005-04-07 07:30:20 +00002083 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002084 {
pauleb821182004-05-01 08:44:08 +00002085 if (sockunion_same (&peer->su, su)
2086 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2087 {
2088 if (peer->as == remote_as
2089 && peer->remote_id.s_addr == 0)
2090 return peer;
2091 if (peer->as == remote_as)
2092 *as = 1;
2093 }
paul718e3742002-12-13 20:15:29 +00002094 }
2095 return NULL;
2096}
2097
2098/* If peer is configured at least one address family return 1. */
2099int
2100peer_active (struct peer *peer)
2101{
2102 if (peer->afc[AFI_IP][SAFI_UNICAST]
2103 || peer->afc[AFI_IP][SAFI_MULTICAST]
2104 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2105 || peer->afc[AFI_IP6][SAFI_UNICAST]
2106 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2107 return 1;
2108 return 0;
2109}
2110
2111/* If peer is negotiated at least one address family return 1. */
2112int
2113peer_active_nego (struct peer *peer)
2114{
2115 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2116 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2117 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2118 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2119 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2120 return 1;
2121 return 0;
2122}
2123
2124/* peer_flag_change_type. */
2125enum peer_change_type
2126{
2127 peer_change_none,
2128 peer_change_reset,
2129 peer_change_reset_in,
2130 peer_change_reset_out,
2131};
2132
paul94f2b392005-06-28 12:44:16 +00002133static void
paul718e3742002-12-13 20:15:29 +00002134peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2135 enum peer_change_type type)
2136{
2137 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2138 return;
2139
2140 if (type == peer_change_reset)
2141 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2142 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2143 else if (type == peer_change_reset_in)
2144 {
2145 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2146 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2147 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2148 else
2149 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2150 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2151 }
2152 else if (type == peer_change_reset_out)
2153 bgp_announce_route (peer, afi, safi);
2154}
2155
2156struct peer_flag_action
2157{
2158 /* Peer's flag. */
2159 u_int32_t flag;
2160
2161 /* This flag can be set for peer-group member. */
2162 u_char not_for_member;
2163
2164 /* Action when the flag is changed. */
2165 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002166
2167 /* Peer down cause */
2168 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002169};
2170
2171struct peer_flag_action peer_flag_action_list[] =
2172 {
2173 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2174 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2175 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2176 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2177 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002178 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002179 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002180 { 0, 0, 0 }
2181 };
2182
2183struct peer_flag_action peer_af_flag_action_list[] =
2184 {
2185 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2186 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2187 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2188 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2189 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2190 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2191 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2192 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2193 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2194 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2195 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2196 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2197 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002198 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002199 { 0, 0, 0 }
2200 };
2201
2202/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002203static int
paul718e3742002-12-13 20:15:29 +00002204peer_flag_action_set (struct peer_flag_action *action_list, int size,
2205 struct peer_flag_action *action, u_int32_t flag)
2206{
2207 int i;
2208 int found = 0;
2209 int reset_in = 0;
2210 int reset_out = 0;
2211 struct peer_flag_action *match = NULL;
2212
2213 /* Check peer's frag action. */
2214 for (i = 0; i < size; i++)
2215 {
2216 match = &action_list[i];
2217
2218 if (match->flag == 0)
2219 break;
2220
2221 if (match->flag & flag)
2222 {
2223 found = 1;
2224
2225 if (match->type == peer_change_reset_in)
2226 reset_in = 1;
2227 if (match->type == peer_change_reset_out)
2228 reset_out = 1;
2229 if (match->type == peer_change_reset)
2230 {
2231 reset_in = 1;
2232 reset_out = 1;
2233 }
2234 if (match->not_for_member)
2235 action->not_for_member = 1;
2236 }
2237 }
2238
2239 /* Set peer clear type. */
2240 if (reset_in && reset_out)
2241 action->type = peer_change_reset;
2242 else if (reset_in)
2243 action->type = peer_change_reset_in;
2244 else if (reset_out)
2245 action->type = peer_change_reset_out;
2246 else
2247 action->type = peer_change_none;
2248
2249 return found;
2250}
2251
paul94f2b392005-06-28 12:44:16 +00002252static void
paul718e3742002-12-13 20:15:29 +00002253peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2254{
2255 if (flag == PEER_FLAG_SHUTDOWN)
2256 {
2257 if (CHECK_FLAG (peer->flags, flag))
2258 {
hasso93406d82005-02-02 14:40:33 +00002259 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2260 peer_nsf_stop (peer);
2261
hasso0a486e52005-02-01 20:57:17 +00002262 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2263 if (peer->t_pmax_restart)
2264 {
2265 BGP_TIMER_OFF (peer->t_pmax_restart);
2266 if (BGP_DEBUG (events, EVENTS))
2267 zlog_debug ("%s Maximum-prefix restart timer canceled",
2268 peer->host);
2269 }
2270
hasso93406d82005-02-02 14:40:33 +00002271 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2272 peer_nsf_stop (peer);
2273
paul718e3742002-12-13 20:15:29 +00002274 if (peer->status == Established)
2275 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2276 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2277 else
2278 BGP_EVENT_ADD (peer, BGP_Stop);
2279 }
2280 else
2281 {
2282 peer->v_start = BGP_INIT_START_TIMER;
2283 BGP_EVENT_ADD (peer, BGP_Stop);
2284 }
2285 }
2286 else if (peer->status == Established)
2287 {
hassoc9502432005-02-01 22:01:48 +00002288 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2289 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2290 else if (flag == PEER_FLAG_PASSIVE)
2291 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002292 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002293 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002294
hassoc9502432005-02-01 22:01:48 +00002295 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002297 }
2298 else
2299 BGP_EVENT_ADD (peer, BGP_Stop);
2300}
2301
2302/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002303static int
paul718e3742002-12-13 20:15:29 +00002304peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2305{
2306 int found;
2307 int size;
2308 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002309 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002310 struct peer_flag_action action;
2311
2312 memset (&action, 0, sizeof (struct peer_flag_action));
2313 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2314
2315 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2316
2317 /* No flag action is found. */
2318 if (! found)
2319 return BGP_ERR_INVALID_FLAG;
2320
2321 /* Not for peer-group member. */
2322 if (action.not_for_member && peer_group_active (peer))
2323 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2324
2325 /* When unset the peer-group member's flag we have to check
2326 peer-group configuration. */
2327 if (! set && peer_group_active (peer))
2328 if (CHECK_FLAG (peer->group->conf->flags, flag))
2329 {
2330 if (flag == PEER_FLAG_SHUTDOWN)
2331 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2332 else
2333 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2334 }
2335
2336 /* Flag conflict check. */
2337 if (set
2338 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2339 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2340 return BGP_ERR_PEER_FLAG_CONFLICT;
2341
2342 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2343 {
2344 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2345 return 0;
2346 if (! set && ! CHECK_FLAG (peer->flags, flag))
2347 return 0;
2348 }
2349
2350 if (set)
2351 SET_FLAG (peer->flags, flag);
2352 else
2353 UNSET_FLAG (peer->flags, flag);
2354
2355 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2356 {
2357 if (action.type == peer_change_reset)
2358 peer_flag_modify_action (peer, flag);
2359
2360 return 0;
2361 }
2362
2363 /* peer-group member updates. */
2364 group = peer->group;
2365
paul1eb8ef22005-04-07 07:30:20 +00002366 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002367 {
2368 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2369 continue;
2370
2371 if (! set && ! CHECK_FLAG (peer->flags, flag))
2372 continue;
2373
2374 if (set)
2375 SET_FLAG (peer->flags, flag);
2376 else
2377 UNSET_FLAG (peer->flags, flag);
2378
2379 if (action.type == peer_change_reset)
2380 peer_flag_modify_action (peer, flag);
2381 }
2382 return 0;
2383}
2384
2385int
2386peer_flag_set (struct peer *peer, u_int32_t flag)
2387{
2388 return peer_flag_modify (peer, flag, 1);
2389}
2390
2391int
2392peer_flag_unset (struct peer *peer, u_int32_t flag)
2393{
2394 return peer_flag_modify (peer, flag, 0);
2395}
2396
paul94f2b392005-06-28 12:44:16 +00002397static int
paul718e3742002-12-13 20:15:29 +00002398peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2399{
2400 if (peer->af_group[afi][safi])
2401 return 1;
2402 return 0;
2403}
2404
paul94f2b392005-06-28 12:44:16 +00002405static int
paul718e3742002-12-13 20:15:29 +00002406peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2407 int set)
2408{
2409 int found;
2410 int size;
paul1eb8ef22005-04-07 07:30:20 +00002411 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002412 struct peer_group *group;
2413 struct peer_flag_action action;
2414
2415 memset (&action, 0, sizeof (struct peer_flag_action));
2416 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2417
2418 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2419
2420 /* No flag action is found. */
2421 if (! found)
2422 return BGP_ERR_INVALID_FLAG;
2423
2424 /* Adress family must be activated. */
2425 if (! peer->afc[afi][safi])
2426 return BGP_ERR_PEER_INACTIVE;
2427
2428 /* Not for peer-group member. */
2429 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2430 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2431
2432 /* Spcecial check for reflector client. */
2433 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2434 && peer_sort (peer) != BGP_PEER_IBGP)
2435 return BGP_ERR_NOT_INTERNAL_PEER;
2436
2437 /* Spcecial check for remove-private-AS. */
2438 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2439 && peer_sort (peer) == BGP_PEER_IBGP)
2440 return BGP_ERR_REMOVE_PRIVATE_AS;
2441
2442 /* When unset the peer-group member's flag we have to check
2443 peer-group configuration. */
2444 if (! set && peer->af_group[afi][safi])
2445 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2446 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2447
2448 /* When current flag configuration is same as requested one. */
2449 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2450 {
2451 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2452 return 0;
2453 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2454 return 0;
2455 }
2456
2457 if (set)
2458 SET_FLAG (peer->af_flags[afi][safi], flag);
2459 else
2460 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2461
2462 /* Execute action when peer is established. */
2463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2464 && peer->status == Established)
2465 {
2466 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2467 bgp_clear_adj_in (peer, afi, safi);
2468 else
hassoe0701b72004-05-20 09:19:34 +00002469 {
2470 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2471 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2472 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2473 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2474 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2475 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2476 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2477 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2478
2479 peer_change_action (peer, afi, safi, action.type);
2480 }
2481
paul718e3742002-12-13 20:15:29 +00002482 }
2483
2484 /* Peer group member updates. */
2485 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2486 {
2487 group = peer->group;
2488
paul1eb8ef22005-04-07 07:30:20 +00002489 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002490 {
2491 if (! peer->af_group[afi][safi])
2492 continue;
2493
2494 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2495 continue;
2496
2497 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2498 continue;
2499
2500 if (set)
2501 SET_FLAG (peer->af_flags[afi][safi], flag);
2502 else
2503 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2504
2505 if (peer->status == Established)
2506 {
2507 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2508 bgp_clear_adj_in (peer, afi, safi);
2509 else
hassoe0701b72004-05-20 09:19:34 +00002510 {
2511 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2512 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2513 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2514 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2515 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2516 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2517 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2518 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2519
2520 peer_change_action (peer, afi, safi, action.type);
2521 }
paul718e3742002-12-13 20:15:29 +00002522 }
2523 }
2524 }
2525 return 0;
2526}
2527
2528int
2529peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2530{
2531 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2532}
2533
2534int
2535peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2536{
2537 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2538}
2539
2540/* EBGP multihop configuration. */
2541int
2542peer_ebgp_multihop_set (struct peer *peer, int ttl)
2543{
2544 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002545 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002546
2547 if (peer_sort (peer) == BGP_PEER_IBGP)
2548 return 0;
2549
2550 peer->ttl = ttl;
2551
2552 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2553 {
pauleb821182004-05-01 08:44:08 +00002554 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2555 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002556 }
2557 else
2558 {
2559 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002560 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002561 {
2562 if (peer_sort (peer) == BGP_PEER_IBGP)
2563 continue;
paul718e3742002-12-13 20:15:29 +00002564
pauleb821182004-05-01 08:44:08 +00002565 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002566
pauleb821182004-05-01 08:44:08 +00002567 if (peer->fd >= 0)
2568 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2569 }
paul718e3742002-12-13 20:15:29 +00002570 }
2571 return 0;
2572}
2573
2574int
2575peer_ebgp_multihop_unset (struct peer *peer)
2576{
2577 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002578 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002579
2580 if (peer_sort (peer) == BGP_PEER_IBGP)
2581 return 0;
2582
2583 if (peer_group_active (peer))
2584 peer->ttl = peer->group->conf->ttl;
2585 else
2586 peer->ttl = 1;
2587
2588 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2589 {
pauleb821182004-05-01 08:44:08 +00002590 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2591 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002592 }
2593 else
2594 {
2595 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002596 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002597 {
2598 if (peer_sort (peer) == BGP_PEER_IBGP)
2599 continue;
paul718e3742002-12-13 20:15:29 +00002600
pauleb821182004-05-01 08:44:08 +00002601 peer->ttl = 1;
2602
2603 if (peer->fd >= 0)
2604 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2605 }
paul718e3742002-12-13 20:15:29 +00002606 }
2607 return 0;
2608}
2609
2610/* Neighbor description. */
2611int
2612peer_description_set (struct peer *peer, char *desc)
2613{
2614 if (peer->desc)
2615 XFREE (MTYPE_PEER_DESC, peer->desc);
2616
2617 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2618
2619 return 0;
2620}
2621
2622int
2623peer_description_unset (struct peer *peer)
2624{
2625 if (peer->desc)
2626 XFREE (MTYPE_PEER_DESC, peer->desc);
2627
2628 peer->desc = NULL;
2629
2630 return 0;
2631}
2632
2633/* Neighbor update-source. */
2634int
paulfd79ac92004-10-13 05:06:08 +00002635peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002636{
2637 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002638 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002639
2640 if (peer->update_if)
2641 {
2642 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2643 && strcmp (peer->update_if, ifname) == 0)
2644 return 0;
2645
2646 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2647 peer->update_if = NULL;
2648 }
2649
2650 if (peer->update_source)
2651 {
2652 sockunion_free (peer->update_source);
2653 peer->update_source = NULL;
2654 }
2655
2656 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2657
2658 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2659 {
2660 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002661 {
2662 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2663 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2664 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2665 }
paul718e3742002-12-13 20:15:29 +00002666 else
2667 BGP_EVENT_ADD (peer, BGP_Stop);
2668 return 0;
2669 }
2670
2671 /* peer-group member updates. */
2672 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002673 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002674 {
2675 if (peer->update_if)
2676 {
2677 if (strcmp (peer->update_if, ifname) == 0)
2678 continue;
2679
2680 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2681 peer->update_if = NULL;
2682 }
2683
2684 if (peer->update_source)
2685 {
2686 sockunion_free (peer->update_source);
2687 peer->update_source = NULL;
2688 }
2689
2690 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2691
2692 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002693 {
2694 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2695 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2696 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2697 }
paul718e3742002-12-13 20:15:29 +00002698 else
2699 BGP_EVENT_ADD (peer, BGP_Stop);
2700 }
2701 return 0;
2702}
2703
2704int
2705peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2706{
2707 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002708 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002709
2710 if (peer->update_source)
2711 {
2712 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2713 && sockunion_cmp (peer->update_source, su) == 0)
2714 return 0;
2715 sockunion_free (peer->update_source);
2716 peer->update_source = NULL;
2717 }
2718
2719 if (peer->update_if)
2720 {
2721 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2722 peer->update_if = NULL;
2723 }
2724
2725 peer->update_source = sockunion_dup (su);
2726
2727 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2728 {
2729 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002730 {
2731 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2732 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2733 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2734 }
paul718e3742002-12-13 20:15:29 +00002735 else
2736 BGP_EVENT_ADD (peer, BGP_Stop);
2737 return 0;
2738 }
2739
2740 /* peer-group member updates. */
2741 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002742 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002743 {
2744 if (peer->update_source)
2745 {
2746 if (sockunion_cmp (peer->update_source, su) == 0)
2747 continue;
2748 sockunion_free (peer->update_source);
2749 peer->update_source = NULL;
2750 }
2751
2752 if (peer->update_if)
2753 {
2754 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2755 peer->update_if = NULL;
2756 }
2757
2758 peer->update_source = sockunion_dup (su);
2759
2760 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002761 {
2762 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2763 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2764 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2765 }
paul718e3742002-12-13 20:15:29 +00002766 else
2767 BGP_EVENT_ADD (peer, BGP_Stop);
2768 }
2769 return 0;
2770}
2771
2772int
2773peer_update_source_unset (struct peer *peer)
2774{
2775 union sockunion *su;
2776 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002778
2779 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2780 && ! peer->update_source
2781 && ! peer->update_if)
2782 return 0;
2783
2784 if (peer->update_source)
2785 {
2786 sockunion_free (peer->update_source);
2787 peer->update_source = NULL;
2788 }
2789 if (peer->update_if)
2790 {
2791 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2792 peer->update_if = NULL;
2793 }
2794
2795 if (peer_group_active (peer))
2796 {
2797 group = peer->group;
2798
2799 if (group->conf->update_source)
2800 {
2801 su = sockunion_dup (group->conf->update_source);
2802 peer->update_source = su;
2803 }
2804 else if (group->conf->update_if)
2805 peer->update_if =
2806 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2807 }
2808
2809 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2810 {
2811 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002812 {
2813 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2814 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2815 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2816 }
paul718e3742002-12-13 20:15:29 +00002817 else
2818 BGP_EVENT_ADD (peer, BGP_Stop);
2819 return 0;
2820 }
2821
2822 /* peer-group member updates. */
2823 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002824 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002825 {
2826 if (! peer->update_source && ! peer->update_if)
2827 continue;
2828
2829 if (peer->update_source)
2830 {
2831 sockunion_free (peer->update_source);
2832 peer->update_source = NULL;
2833 }
2834
2835 if (peer->update_if)
2836 {
2837 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2838 peer->update_if = NULL;
2839 }
2840
2841 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002842 {
2843 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2844 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2845 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2846 }
paul718e3742002-12-13 20:15:29 +00002847 else
2848 BGP_EVENT_ADD (peer, BGP_Stop);
2849 }
2850 return 0;
2851}
2852
2853int
2854peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002855 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002856{
2857 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002858 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002859
2860 /* Adress family must be activated. */
2861 if (! peer->afc[afi][safi])
2862 return BGP_ERR_PEER_INACTIVE;
2863
2864 /* Default originate can't be used for peer group memeber. */
2865 if (peer_is_group_member (peer, afi, safi))
2866 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2867
2868 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2869 || (rmap && ! peer->default_rmap[afi][safi].name)
2870 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2871 {
2872 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2873
2874 if (rmap)
2875 {
2876 if (peer->default_rmap[afi][safi].name)
2877 free (peer->default_rmap[afi][safi].name);
2878 peer->default_rmap[afi][safi].name = strdup (rmap);
2879 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2880 }
2881 }
2882
2883 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2884 {
2885 if (peer->status == Established && peer->afc_nego[afi][safi])
2886 bgp_default_originate (peer, afi, safi, 0);
2887 return 0;
2888 }
2889
2890 /* peer-group member updates. */
2891 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002892 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002893 {
2894 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2895
2896 if (rmap)
2897 {
2898 if (peer->default_rmap[afi][safi].name)
2899 free (peer->default_rmap[afi][safi].name);
2900 peer->default_rmap[afi][safi].name = strdup (rmap);
2901 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2902 }
2903
2904 if (peer->status == Established && peer->afc_nego[afi][safi])
2905 bgp_default_originate (peer, afi, safi, 0);
2906 }
2907 return 0;
2908}
2909
2910int
2911peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2912{
2913 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002915
2916 /* Adress family must be activated. */
2917 if (! peer->afc[afi][safi])
2918 return BGP_ERR_PEER_INACTIVE;
2919
2920 /* Default originate can't be used for peer group memeber. */
2921 if (peer_is_group_member (peer, afi, safi))
2922 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2923
2924 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2925 {
2926 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2927
2928 if (peer->default_rmap[afi][safi].name)
2929 free (peer->default_rmap[afi][safi].name);
2930 peer->default_rmap[afi][safi].name = NULL;
2931 peer->default_rmap[afi][safi].map = NULL;
2932 }
2933
2934 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2935 {
2936 if (peer->status == Established && peer->afc_nego[afi][safi])
2937 bgp_default_originate (peer, afi, safi, 1);
2938 return 0;
2939 }
2940
2941 /* peer-group member updates. */
2942 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002943 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002944 {
2945 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2946
2947 if (peer->default_rmap[afi][safi].name)
2948 free (peer->default_rmap[afi][safi].name);
2949 peer->default_rmap[afi][safi].name = NULL;
2950 peer->default_rmap[afi][safi].map = NULL;
2951
2952 if (peer->status == Established && peer->afc_nego[afi][safi])
2953 bgp_default_originate (peer, afi, safi, 1);
2954 }
2955 return 0;
2956}
2957
2958int
2959peer_port_set (struct peer *peer, u_int16_t port)
2960{
2961 peer->port = port;
2962 return 0;
2963}
2964
2965int
2966peer_port_unset (struct peer *peer)
2967{
2968 peer->port = BGP_PORT_DEFAULT;
2969 return 0;
2970}
2971
2972/* neighbor weight. */
2973int
2974peer_weight_set (struct peer *peer, u_int16_t weight)
2975{
2976 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002977 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002978
2979 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2980 peer->weight = weight;
2981
2982 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2983 return 0;
2984
2985 /* peer-group member updates. */
2986 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002987 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002988 {
2989 peer->weight = group->conf->weight;
2990 }
2991 return 0;
2992}
2993
2994int
2995peer_weight_unset (struct peer *peer)
2996{
2997 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002998 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002999
3000 /* Set default weight. */
3001 if (peer_group_active (peer))
3002 peer->weight = peer->group->conf->weight;
3003 else
3004 peer->weight = 0;
3005
3006 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3007
3008 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3009 return 0;
3010
3011 /* peer-group member updates. */
3012 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003013 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003014 {
3015 peer->weight = 0;
3016 }
3017 return 0;
3018}
3019
3020int
3021peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3022{
3023 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003024 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003025
3026 /* Not for peer group memeber. */
3027 if (peer_group_active (peer))
3028 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3029
3030 /* keepalive value check. */
3031 if (keepalive > 65535)
3032 return BGP_ERR_INVALID_VALUE;
3033
3034 /* Holdtime value check. */
3035 if (holdtime > 65535)
3036 return BGP_ERR_INVALID_VALUE;
3037
3038 /* Holdtime value must be either 0 or greater than 3. */
3039 if (holdtime < 3 && holdtime != 0)
3040 return BGP_ERR_INVALID_VALUE;
3041
3042 /* Set value to the configuration. */
3043 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3044 peer->holdtime = holdtime;
3045 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3046
3047 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3048 return 0;
3049
3050 /* peer-group member updates. */
3051 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003052 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003053 {
3054 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3055 peer->holdtime = group->conf->holdtime;
3056 peer->keepalive = group->conf->keepalive;
3057 }
3058 return 0;
3059}
3060
3061int
3062peer_timers_unset (struct peer *peer)
3063{
3064 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003065 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003066
3067 if (peer_group_active (peer))
3068 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3069
3070 /* Clear configuration. */
3071 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3072 peer->keepalive = 0;
3073 peer->holdtime = 0;
3074
3075 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3076 return 0;
3077
3078 /* peer-group member updates. */
3079 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003080 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003081 {
3082 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3083 peer->holdtime = 0;
3084 peer->keepalive = 0;
3085 }
3086
3087 return 0;
3088}
3089
3090int
3091peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3092{
3093 if (peer_group_active (peer))
3094 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3095
3096 if (connect > 65535)
3097 return BGP_ERR_INVALID_VALUE;
3098
3099 /* Set value to the configuration. */
3100 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3101 peer->connect = connect;
3102
3103 /* Set value to timer setting. */
3104 peer->v_connect = connect;
3105
3106 return 0;
3107}
3108
3109int
3110peer_timers_connect_unset (struct peer *peer)
3111{
3112 if (peer_group_active (peer))
3113 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3114
3115 /* Clear configuration. */
3116 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3117 peer->connect = 0;
3118
3119 /* Set timer setting to default value. */
3120 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3121
3122 return 0;
3123}
3124
3125int
3126peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3127{
3128 if (peer_group_active (peer))
3129 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3130
3131 if (routeadv > 600)
3132 return BGP_ERR_INVALID_VALUE;
3133
3134 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3135 peer->routeadv = routeadv;
3136 peer->v_routeadv = routeadv;
3137
3138 return 0;
3139}
3140
3141int
3142peer_advertise_interval_unset (struct peer *peer)
3143{
3144 if (peer_group_active (peer))
3145 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3146
3147 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3148 peer->routeadv = 0;
3149
3150 if (peer_sort (peer) == BGP_PEER_IBGP)
3151 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3152 else
3153 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3154
3155 return 0;
3156}
3157
paul718e3742002-12-13 20:15:29 +00003158/* neighbor interface */
3159int
paulfd79ac92004-10-13 05:06:08 +00003160peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003161{
3162 if (peer->ifname)
3163 free (peer->ifname);
3164 peer->ifname = strdup (str);
3165
3166 return 0;
3167}
3168
3169int
3170peer_interface_unset (struct peer *peer)
3171{
3172 if (peer->ifname)
3173 free (peer->ifname);
3174 peer->ifname = NULL;
3175
3176 return 0;
3177}
3178
3179/* Allow-as in. */
3180int
3181peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3182{
3183 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003184 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003185
3186 if (allow_num < 1 || allow_num > 10)
3187 return BGP_ERR_INVALID_VALUE;
3188
3189 if (peer->allowas_in[afi][safi] != allow_num)
3190 {
3191 peer->allowas_in[afi][safi] = allow_num;
3192 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3193 peer_change_action (peer, afi, safi, peer_change_reset_in);
3194 }
3195
3196 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3197 return 0;
3198
3199 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003200 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003201 {
3202 if (peer->allowas_in[afi][safi] != allow_num)
3203 {
3204 peer->allowas_in[afi][safi] = allow_num;
3205 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3206 peer_change_action (peer, afi, safi, peer_change_reset_in);
3207 }
3208
3209 }
3210 return 0;
3211}
3212
3213int
3214peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3215{
3216 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003217 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003218
3219 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3220 {
3221 peer->allowas_in[afi][safi] = 0;
3222 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3223 }
3224
3225 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3226 return 0;
3227
3228 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003229 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003230 {
3231 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3232 {
3233 peer->allowas_in[afi][safi] = 0;
3234 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3235 }
3236 }
3237 return 0;
3238}
3239
3240int
3241peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3242{
3243 struct bgp *bgp = peer->bgp;
3244 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003245 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003246
3247 if (peer_sort (peer) != BGP_PEER_EBGP
3248 && peer_sort (peer) != BGP_PEER_INTERNAL)
3249 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3250
3251 if (bgp->as == as)
3252 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3253
3254 if (peer_group_active (peer))
3255 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3256
3257 if (peer->change_local_as == as &&
3258 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3259 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3260 return 0;
3261
3262 peer->change_local_as = as;
3263 if (no_prepend)
3264 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3265 else
3266 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3267
3268 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3269 {
3270 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003271 {
3272 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3273 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3274 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3275 }
paul718e3742002-12-13 20:15:29 +00003276 else
3277 BGP_EVENT_ADD (peer, BGP_Stop);
3278
3279 return 0;
3280 }
3281
3282 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003283 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003284 {
3285 peer->change_local_as = as;
3286 if (no_prepend)
3287 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3288 else
3289 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3290
3291 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003292 {
3293 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3294 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3295 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3296 }
paul718e3742002-12-13 20:15:29 +00003297 else
3298 BGP_EVENT_ADD (peer, BGP_Stop);
3299 }
3300
3301 return 0;
3302}
3303
3304int
3305peer_local_as_unset (struct peer *peer)
3306{
3307 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003308 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003309
3310 if (peer_group_active (peer))
3311 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3312
3313 if (! peer->change_local_as)
3314 return 0;
3315
3316 peer->change_local_as = 0;
3317 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3318
3319 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3320 {
3321 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003322 {
3323 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3324 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3325 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3326 }
paul718e3742002-12-13 20:15:29 +00003327 else
3328 BGP_EVENT_ADD (peer, BGP_Stop);
3329
3330 return 0;
3331 }
3332
3333 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003334 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003335 {
3336 peer->change_local_as = 0;
3337 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3338
3339 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003340 {
3341 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3342 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3343 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3344 }
paul718e3742002-12-13 20:15:29 +00003345 else
3346 BGP_EVENT_ADD (peer, BGP_Stop);
3347 }
3348 return 0;
3349}
3350
3351/* Set distribute list to the peer. */
3352int
3353peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003354 const char *name)
paul718e3742002-12-13 20:15:29 +00003355{
3356 struct bgp_filter *filter;
3357 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003358 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003359
3360 if (! peer->afc[afi][safi])
3361 return BGP_ERR_PEER_INACTIVE;
3362
3363 if (direct != FILTER_IN && direct != FILTER_OUT)
3364 return BGP_ERR_INVALID_VALUE;
3365
3366 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3367 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3368
3369 filter = &peer->filter[afi][safi];
3370
3371 if (filter->plist[direct].name)
3372 return BGP_ERR_PEER_FILTER_CONFLICT;
3373
3374 if (filter->dlist[direct].name)
3375 free (filter->dlist[direct].name);
3376 filter->dlist[direct].name = strdup (name);
3377 filter->dlist[direct].alist = access_list_lookup (afi, name);
3378
3379 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3380 return 0;
3381
3382 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003383 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003384 {
3385 filter = &peer->filter[afi][safi];
3386
3387 if (! peer->af_group[afi][safi])
3388 continue;
3389
3390 if (filter->dlist[direct].name)
3391 free (filter->dlist[direct].name);
3392 filter->dlist[direct].name = strdup (name);
3393 filter->dlist[direct].alist = access_list_lookup (afi, name);
3394 }
3395
3396 return 0;
3397}
3398
3399int
3400peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3401{
3402 struct bgp_filter *filter;
3403 struct bgp_filter *gfilter;
3404 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003405 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003406
3407 if (! peer->afc[afi][safi])
3408 return BGP_ERR_PEER_INACTIVE;
3409
3410 if (direct != FILTER_IN && direct != FILTER_OUT)
3411 return BGP_ERR_INVALID_VALUE;
3412
3413 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3414 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3415
3416 filter = &peer->filter[afi][safi];
3417
3418 /* apply peer-group filter */
3419 if (peer->af_group[afi][safi])
3420 {
3421 gfilter = &peer->group->conf->filter[afi][safi];
3422
3423 if (gfilter->dlist[direct].name)
3424 {
3425 if (filter->dlist[direct].name)
3426 free (filter->dlist[direct].name);
3427 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3428 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3429 return 0;
3430 }
3431 }
3432
3433 if (filter->dlist[direct].name)
3434 free (filter->dlist[direct].name);
3435 filter->dlist[direct].name = NULL;
3436 filter->dlist[direct].alist = NULL;
3437
3438 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3439 return 0;
3440
3441 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003442 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003443 {
3444 filter = &peer->filter[afi][safi];
3445
3446 if (! peer->af_group[afi][safi])
3447 continue;
3448
3449 if (filter->dlist[direct].name)
3450 free (filter->dlist[direct].name);
3451 filter->dlist[direct].name = NULL;
3452 filter->dlist[direct].alist = NULL;
3453 }
3454
3455 return 0;
3456}
3457
3458/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003459static void
paul718e3742002-12-13 20:15:29 +00003460peer_distribute_update (struct access_list *access)
3461{
3462 afi_t afi;
3463 safi_t safi;
3464 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003465 struct listnode *mnode, *mnnode;
3466 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003467 struct bgp *bgp;
3468 struct peer *peer;
3469 struct peer_group *group;
3470 struct bgp_filter *filter;
3471
paul1eb8ef22005-04-07 07:30:20 +00003472 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003473 {
paul1eb8ef22005-04-07 07:30:20 +00003474 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003475 {
3476 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3477 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3478 {
3479 filter = &peer->filter[afi][safi];
3480
3481 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3482 {
3483 if (filter->dlist[direct].name)
3484 filter->dlist[direct].alist =
3485 access_list_lookup (afi, filter->dlist[direct].name);
3486 else
3487 filter->dlist[direct].alist = NULL;
3488 }
3489 }
3490 }
paul1eb8ef22005-04-07 07:30:20 +00003491 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003492 {
3493 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3494 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3495 {
3496 filter = &group->conf->filter[afi][safi];
3497
3498 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3499 {
3500 if (filter->dlist[direct].name)
3501 filter->dlist[direct].alist =
3502 access_list_lookup (afi, filter->dlist[direct].name);
3503 else
3504 filter->dlist[direct].alist = NULL;
3505 }
3506 }
3507 }
3508 }
3509}
3510
3511/* Set prefix list to the peer. */
3512int
3513peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003514 const char *name)
paul718e3742002-12-13 20:15:29 +00003515{
3516 struct bgp_filter *filter;
3517 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003518 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003519
3520 if (! peer->afc[afi][safi])
3521 return BGP_ERR_PEER_INACTIVE;
3522
3523 if (direct != FILTER_IN && direct != FILTER_OUT)
3524 return BGP_ERR_INVALID_VALUE;
3525
3526 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3527 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3528
3529 filter = &peer->filter[afi][safi];
3530
3531 if (filter->dlist[direct].name)
3532 return BGP_ERR_PEER_FILTER_CONFLICT;
3533
3534 if (filter->plist[direct].name)
3535 free (filter->plist[direct].name);
3536 filter->plist[direct].name = strdup (name);
3537 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3538
3539 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3540 return 0;
3541
3542 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003543 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003544 {
3545 filter = &peer->filter[afi][safi];
3546
3547 if (! peer->af_group[afi][safi])
3548 continue;
3549
3550 if (filter->plist[direct].name)
3551 free (filter->plist[direct].name);
3552 filter->plist[direct].name = strdup (name);
3553 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3554 }
3555 return 0;
3556}
3557
3558int
3559peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3560{
3561 struct bgp_filter *filter;
3562 struct bgp_filter *gfilter;
3563 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003564 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003565
3566 if (! peer->afc[afi][safi])
3567 return BGP_ERR_PEER_INACTIVE;
3568
3569 if (direct != FILTER_IN && direct != FILTER_OUT)
3570 return BGP_ERR_INVALID_VALUE;
3571
3572 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3573 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3574
3575 filter = &peer->filter[afi][safi];
3576
3577 /* apply peer-group filter */
3578 if (peer->af_group[afi][safi])
3579 {
3580 gfilter = &peer->group->conf->filter[afi][safi];
3581
3582 if (gfilter->plist[direct].name)
3583 {
3584 if (filter->plist[direct].name)
3585 free (filter->plist[direct].name);
3586 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3587 filter->plist[direct].plist = gfilter->plist[direct].plist;
3588 return 0;
3589 }
3590 }
3591
3592 if (filter->plist[direct].name)
3593 free (filter->plist[direct].name);
3594 filter->plist[direct].name = NULL;
3595 filter->plist[direct].plist = NULL;
3596
3597 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3598 return 0;
3599
3600 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003601 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003602 {
3603 filter = &peer->filter[afi][safi];
3604
3605 if (! peer->af_group[afi][safi])
3606 continue;
3607
3608 if (filter->plist[direct].name)
3609 free (filter->plist[direct].name);
3610 filter->plist[direct].name = NULL;
3611 filter->plist[direct].plist = NULL;
3612 }
3613
3614 return 0;
3615}
3616
3617/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003618static void
paul718e3742002-12-13 20:15:29 +00003619peer_prefix_list_update (struct prefix_list *plist)
3620{
paul1eb8ef22005-04-07 07:30:20 +00003621 struct listnode *mnode, *mnnode;
3622 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003623 struct bgp *bgp;
3624 struct peer *peer;
3625 struct peer_group *group;
3626 struct bgp_filter *filter;
3627 afi_t afi;
3628 safi_t safi;
3629 int direct;
3630
paul1eb8ef22005-04-07 07:30:20 +00003631 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003632 {
paul1eb8ef22005-04-07 07:30:20 +00003633 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003634 {
3635 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3636 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3637 {
3638 filter = &peer->filter[afi][safi];
3639
3640 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3641 {
3642 if (filter->plist[direct].name)
3643 filter->plist[direct].plist =
3644 prefix_list_lookup (afi, filter->plist[direct].name);
3645 else
3646 filter->plist[direct].plist = NULL;
3647 }
3648 }
3649 }
paul1eb8ef22005-04-07 07:30:20 +00003650 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003651 {
3652 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3653 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3654 {
3655 filter = &group->conf->filter[afi][safi];
3656
3657 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3658 {
3659 if (filter->plist[direct].name)
3660 filter->plist[direct].plist =
3661 prefix_list_lookup (afi, filter->plist[direct].name);
3662 else
3663 filter->plist[direct].plist = NULL;
3664 }
3665 }
3666 }
3667 }
3668}
3669
3670int
3671peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003672 const char *name)
paul718e3742002-12-13 20:15:29 +00003673{
3674 struct bgp_filter *filter;
3675 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003676 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003677
3678 if (! peer->afc[afi][safi])
3679 return BGP_ERR_PEER_INACTIVE;
3680
3681 if (direct != FILTER_IN && direct != FILTER_OUT)
3682 return BGP_ERR_INVALID_VALUE;
3683
3684 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3685 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3686
3687 filter = &peer->filter[afi][safi];
3688
3689 if (filter->aslist[direct].name)
3690 free (filter->aslist[direct].name);
3691 filter->aslist[direct].name = strdup (name);
3692 filter->aslist[direct].aslist = as_list_lookup (name);
3693
3694 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3695 return 0;
3696
3697 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003698 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003699 {
3700 filter = &peer->filter[afi][safi];
3701
3702 if (! peer->af_group[afi][safi])
3703 continue;
3704
3705 if (filter->aslist[direct].name)
3706 free (filter->aslist[direct].name);
3707 filter->aslist[direct].name = strdup (name);
3708 filter->aslist[direct].aslist = as_list_lookup (name);
3709 }
3710 return 0;
3711}
3712
3713int
3714peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3715{
3716 struct bgp_filter *filter;
3717 struct bgp_filter *gfilter;
3718 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003719 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003720
3721 if (! peer->afc[afi][safi])
3722 return BGP_ERR_PEER_INACTIVE;
3723
hassob5f29602005-05-25 21:00:28 +00003724 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003725 return BGP_ERR_INVALID_VALUE;
3726
hassob5f29602005-05-25 21:00:28 +00003727 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003728 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3729
3730 filter = &peer->filter[afi][safi];
3731
3732 /* apply peer-group filter */
3733 if (peer->af_group[afi][safi])
3734 {
3735 gfilter = &peer->group->conf->filter[afi][safi];
3736
3737 if (gfilter->aslist[direct].name)
3738 {
3739 if (filter->aslist[direct].name)
3740 free (filter->aslist[direct].name);
3741 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3742 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3743 return 0;
3744 }
3745 }
3746
3747 if (filter->aslist[direct].name)
3748 free (filter->aslist[direct].name);
3749 filter->aslist[direct].name = NULL;
3750 filter->aslist[direct].aslist = NULL;
3751
3752 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3753 return 0;
3754
3755 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003756 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003757 {
3758 filter = &peer->filter[afi][safi];
3759
3760 if (! peer->af_group[afi][safi])
3761 continue;
3762
3763 if (filter->aslist[direct].name)
3764 free (filter->aslist[direct].name);
3765 filter->aslist[direct].name = NULL;
3766 filter->aslist[direct].aslist = NULL;
3767 }
3768
3769 return 0;
3770}
3771
paul94f2b392005-06-28 12:44:16 +00003772static void
paul718e3742002-12-13 20:15:29 +00003773peer_aslist_update ()
3774{
3775 afi_t afi;
3776 safi_t safi;
3777 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003778 struct listnode *mnode, *mnnode;
3779 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003780 struct bgp *bgp;
3781 struct peer *peer;
3782 struct peer_group *group;
3783 struct bgp_filter *filter;
3784
paul1eb8ef22005-04-07 07:30:20 +00003785 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003786 {
paul1eb8ef22005-04-07 07:30:20 +00003787 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003788 {
3789 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3790 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3791 {
3792 filter = &peer->filter[afi][safi];
3793
3794 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3795 {
3796 if (filter->aslist[direct].name)
3797 filter->aslist[direct].aslist =
3798 as_list_lookup (filter->aslist[direct].name);
3799 else
3800 filter->aslist[direct].aslist = NULL;
3801 }
3802 }
3803 }
paul1eb8ef22005-04-07 07:30:20 +00003804 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003805 {
3806 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3807 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3808 {
3809 filter = &group->conf->filter[afi][safi];
3810
3811 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3812 {
3813 if (filter->aslist[direct].name)
3814 filter->aslist[direct].aslist =
3815 as_list_lookup (filter->aslist[direct].name);
3816 else
3817 filter->aslist[direct].aslist = NULL;
3818 }
3819 }
3820 }
3821 }
3822}
3823
3824/* Set route-map to the peer. */
3825int
3826peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003827 const char *name)
paul718e3742002-12-13 20:15:29 +00003828{
3829 struct bgp_filter *filter;
3830 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003831 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003832
3833 if (! peer->afc[afi][safi])
3834 return BGP_ERR_PEER_INACTIVE;
3835
paulfee0f4c2004-09-13 05:12:46 +00003836 if (direct != RMAP_IN && direct != RMAP_OUT &&
3837 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003838 return BGP_ERR_INVALID_VALUE;
3839
paulfee0f4c2004-09-13 05:12:46 +00003840 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3841 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003842 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3843
3844 filter = &peer->filter[afi][safi];
3845
3846 if (filter->map[direct].name)
3847 free (filter->map[direct].name);
3848
3849 filter->map[direct].name = strdup (name);
3850 filter->map[direct].map = route_map_lookup_by_name (name);
3851
3852 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3853 return 0;
3854
3855 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003856 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003857 {
3858 filter = &peer->filter[afi][safi];
3859
3860 if (! peer->af_group[afi][safi])
3861 continue;
3862
3863 if (filter->map[direct].name)
3864 free (filter->map[direct].name);
3865 filter->map[direct].name = strdup (name);
3866 filter->map[direct].map = route_map_lookup_by_name (name);
3867 }
3868 return 0;
3869}
3870
3871/* Unset route-map from the peer. */
3872int
3873peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3874{
3875 struct bgp_filter *filter;
3876 struct bgp_filter *gfilter;
3877 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003878 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003879
3880 if (! peer->afc[afi][safi])
3881 return BGP_ERR_PEER_INACTIVE;
3882
hassob5f29602005-05-25 21:00:28 +00003883 if (direct != RMAP_IN && direct != RMAP_OUT &&
3884 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003885 return BGP_ERR_INVALID_VALUE;
3886
hassob5f29602005-05-25 21:00:28 +00003887 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3888 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003889 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3890
3891 filter = &peer->filter[afi][safi];
3892
3893 /* apply peer-group filter */
3894 if (peer->af_group[afi][safi])
3895 {
3896 gfilter = &peer->group->conf->filter[afi][safi];
3897
3898 if (gfilter->map[direct].name)
3899 {
3900 if (filter->map[direct].name)
3901 free (filter->map[direct].name);
3902 filter->map[direct].name = strdup (gfilter->map[direct].name);
3903 filter->map[direct].map = gfilter->map[direct].map;
3904 return 0;
3905 }
3906 }
3907
3908 if (filter->map[direct].name)
3909 free (filter->map[direct].name);
3910 filter->map[direct].name = NULL;
3911 filter->map[direct].map = NULL;
3912
3913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3914 return 0;
3915
3916 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003917 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003918 {
3919 filter = &peer->filter[afi][safi];
3920
3921 if (! peer->af_group[afi][safi])
3922 continue;
3923
3924 if (filter->map[direct].name)
3925 free (filter->map[direct].name);
3926 filter->map[direct].name = NULL;
3927 filter->map[direct].map = NULL;
3928 }
3929 return 0;
3930}
3931
3932/* Set unsuppress-map to the peer. */
3933int
paulfd79ac92004-10-13 05:06:08 +00003934peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3935 const char *name)
paul718e3742002-12-13 20:15:29 +00003936{
3937 struct bgp_filter *filter;
3938 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003939 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003940
3941 if (! peer->afc[afi][safi])
3942 return BGP_ERR_PEER_INACTIVE;
3943
3944 if (peer_is_group_member (peer, afi, safi))
3945 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3946
3947 filter = &peer->filter[afi][safi];
3948
3949 if (filter->usmap.name)
3950 free (filter->usmap.name);
3951
3952 filter->usmap.name = strdup (name);
3953 filter->usmap.map = route_map_lookup_by_name (name);
3954
3955 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3956 return 0;
3957
3958 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003960 {
3961 filter = &peer->filter[afi][safi];
3962
3963 if (! peer->af_group[afi][safi])
3964 continue;
3965
3966 if (filter->usmap.name)
3967 free (filter->usmap.name);
3968 filter->usmap.name = strdup (name);
3969 filter->usmap.map = route_map_lookup_by_name (name);
3970 }
3971 return 0;
3972}
3973
3974/* Unset route-map from the peer. */
3975int
3976peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3977{
3978 struct bgp_filter *filter;
3979 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003980 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003981
3982 if (! peer->afc[afi][safi])
3983 return BGP_ERR_PEER_INACTIVE;
3984
3985 if (peer_is_group_member (peer, afi, safi))
3986 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3987
3988 filter = &peer->filter[afi][safi];
3989
3990 if (filter->usmap.name)
3991 free (filter->usmap.name);
3992 filter->usmap.name = NULL;
3993 filter->usmap.map = NULL;
3994
3995 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3996 return 0;
3997
3998 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003999 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004000 {
4001 filter = &peer->filter[afi][safi];
4002
4003 if (! peer->af_group[afi][safi])
4004 continue;
4005
4006 if (filter->usmap.name)
4007 free (filter->usmap.name);
4008 filter->usmap.name = NULL;
4009 filter->usmap.map = NULL;
4010 }
4011 return 0;
4012}
4013
4014int
4015peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004016 u_int32_t max, u_char threshold,
4017 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004018{
4019 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004020 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004021
4022 if (! peer->afc[afi][safi])
4023 return BGP_ERR_PEER_INACTIVE;
4024
4025 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4026 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004027 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004028 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004029 if (warning)
4030 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4031 else
4032 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4033
4034 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4035 return 0;
4036
4037 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004038 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004039 {
4040 if (! peer->af_group[afi][safi])
4041 continue;
4042
4043 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4044 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004045 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004046 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004047 if (warning)
4048 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4049 else
4050 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4051 }
4052 return 0;
4053}
4054
4055int
4056peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4057{
4058 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004059 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004060
4061 if (! peer->afc[afi][safi])
4062 return BGP_ERR_PEER_INACTIVE;
4063
4064 /* apply peer-group config */
4065 if (peer->af_group[afi][safi])
4066 {
4067 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4068 PEER_FLAG_MAX_PREFIX))
4069 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4070 else
4071 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4072
4073 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4074 PEER_FLAG_MAX_PREFIX_WARNING))
4075 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4076 else
4077 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4078
4079 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004080 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004081 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004082 return 0;
4083 }
4084
4085 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4086 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4087 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004088 peer->pmax_threshold[afi][safi] = 0;
4089 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004090
4091 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4092 return 0;
4093
4094 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004095 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004096 {
4097 if (! peer->af_group[afi][safi])
4098 continue;
4099
4100 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4101 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4102 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004103 peer->pmax_threshold[afi][safi] = 0;
4104 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004105 }
4106 return 0;
4107}
4108
4109int
4110peer_clear (struct peer *peer)
4111{
4112 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4113 {
hasso0a486e52005-02-01 20:57:17 +00004114 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4115 {
4116 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4117 if (peer->t_pmax_restart)
4118 {
4119 BGP_TIMER_OFF (peer->t_pmax_restart);
4120 if (BGP_DEBUG (events, EVENTS))
4121 zlog_debug ("%s Maximum-prefix restart timer canceled",
4122 peer->host);
4123 }
4124 BGP_EVENT_ADD (peer, BGP_Start);
4125 return 0;
4126 }
4127
paul718e3742002-12-13 20:15:29 +00004128 peer->v_start = BGP_INIT_START_TIMER;
4129 if (peer->status == Established)
4130 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4131 BGP_NOTIFY_CEASE_ADMIN_RESET);
4132 else
4133 BGP_EVENT_ADD (peer, BGP_Stop);
4134 }
4135 return 0;
4136}
4137
4138int
4139peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4140 enum bgp_clear_type stype)
4141{
4142 if (peer->status != Established)
4143 return 0;
4144
4145 if (! peer->afc[afi][safi])
4146 return BGP_ERR_AF_UNCONFIGURED;
4147
paulfee0f4c2004-09-13 05:12:46 +00004148 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4149 {
4150 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4151 return 0;
4152 bgp_check_local_routes_rsclient (peer, afi, safi);
4153 bgp_soft_reconfig_rsclient (peer, afi, safi);
4154 }
4155
paul718e3742002-12-13 20:15:29 +00004156 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4157 bgp_announce_route (peer, afi, safi);
4158
4159 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4160 {
4161 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4162 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4163 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4164 {
4165 struct bgp_filter *filter = &peer->filter[afi][safi];
4166 u_char prefix_type;
4167
4168 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4169 prefix_type = ORF_TYPE_PREFIX;
4170 else
4171 prefix_type = ORF_TYPE_PREFIX_OLD;
4172
4173 if (filter->plist[FILTER_IN].plist)
4174 {
4175 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4176 bgp_route_refresh_send (peer, afi, safi,
4177 prefix_type, REFRESH_DEFER, 1);
4178 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4179 REFRESH_IMMEDIATE, 0);
4180 }
4181 else
4182 {
4183 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4184 bgp_route_refresh_send (peer, afi, safi,
4185 prefix_type, REFRESH_IMMEDIATE, 1);
4186 else
4187 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4188 }
4189 return 0;
4190 }
4191 }
4192
4193 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4194 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4195 {
4196 /* If neighbor has soft reconfiguration inbound flag.
4197 Use Adj-RIB-In database. */
4198 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4199 bgp_soft_reconfig_in (peer, afi, safi);
4200 else
4201 {
4202 /* If neighbor has route refresh capability, send route refresh
4203 message to the peer. */
4204 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4205 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4206 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4207 else
4208 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4209 }
4210 }
4211 return 0;
4212}
4213
paulfd79ac92004-10-13 05:06:08 +00004214/* Display peer uptime.*/
4215/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004216char *
4217peer_uptime (time_t uptime2, char *buf, size_t len)
4218{
4219 time_t uptime1;
4220 struct tm *tm;
4221
4222 /* Check buffer length. */
4223 if (len < BGP_UPTIME_LEN)
4224 {
gdtc29fdba2004-12-09 14:46:46 +00004225 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004226 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004227 /* XXX: should return status instead of buf... */
4228 snprintf (buf, len, "<error> ");
4229 return buf;
paul718e3742002-12-13 20:15:29 +00004230 }
4231
4232 /* If there is no connection has been done before print `never'. */
4233 if (uptime2 == 0)
4234 {
4235 snprintf (buf, len, "never ");
4236 return buf;
4237 }
4238
4239 /* Get current time. */
4240 uptime1 = time (NULL);
4241 uptime1 -= uptime2;
4242 tm = gmtime (&uptime1);
4243
4244 /* Making formatted timer strings. */
4245#define ONE_DAY_SECOND 60*60*24
4246#define ONE_WEEK_SECOND 60*60*24*7
4247
4248 if (uptime1 < ONE_DAY_SECOND)
4249 snprintf (buf, len, "%02d:%02d:%02d",
4250 tm->tm_hour, tm->tm_min, tm->tm_sec);
4251 else if (uptime1 < ONE_WEEK_SECOND)
4252 snprintf (buf, len, "%dd%02dh%02dm",
4253 tm->tm_yday, tm->tm_hour, tm->tm_min);
4254 else
4255 snprintf (buf, len, "%02dw%dd%02dh",
4256 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4257 return buf;
4258}
4259
paul94f2b392005-06-28 12:44:16 +00004260static void
paul718e3742002-12-13 20:15:29 +00004261bgp_config_write_filter (struct vty *vty, struct peer *peer,
4262 afi_t afi, safi_t safi)
4263{
4264 struct bgp_filter *filter;
4265 struct bgp_filter *gfilter = NULL;
4266 char *addr;
4267 int in = FILTER_IN;
4268 int out = FILTER_OUT;
4269
4270 addr = peer->host;
4271 filter = &peer->filter[afi][safi];
4272 if (peer->af_group[afi][safi])
4273 gfilter = &peer->group->conf->filter[afi][safi];
4274
4275 /* distribute-list. */
4276 if (filter->dlist[in].name)
4277 if (! gfilter || ! gfilter->dlist[in].name
4278 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4279 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4280 filter->dlist[in].name, VTY_NEWLINE);
4281 if (filter->dlist[out].name && ! gfilter)
4282 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4283 filter->dlist[out].name, VTY_NEWLINE);
4284
4285 /* prefix-list. */
4286 if (filter->plist[in].name)
4287 if (! gfilter || ! gfilter->plist[in].name
4288 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4289 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4290 filter->plist[in].name, VTY_NEWLINE);
4291 if (filter->plist[out].name && ! gfilter)
4292 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4293 filter->plist[out].name, VTY_NEWLINE);
4294
4295 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004296 if (filter->map[RMAP_IN].name)
4297 if (! gfilter || ! gfilter->map[RMAP_IN].name
4298 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004299 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004300 filter->map[RMAP_IN].name, VTY_NEWLINE);
4301 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004302 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004303 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4304 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4305 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4306 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4307 if (filter->map[RMAP_EXPORT].name)
4308 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4309 || strcmp (filter->map[RMAP_EXPORT].name,
4310 gfilter->map[RMAP_EXPORT].name) != 0)
4311 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4312 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004313
4314 /* unsuppress-map */
4315 if (filter->usmap.name && ! gfilter)
4316 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4317 filter->usmap.name, VTY_NEWLINE);
4318
4319 /* filter-list. */
4320 if (filter->aslist[in].name)
4321 if (! gfilter || ! gfilter->aslist[in].name
4322 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4323 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4324 filter->aslist[in].name, VTY_NEWLINE);
4325 if (filter->aslist[out].name && ! gfilter)
4326 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4327 filter->aslist[out].name, VTY_NEWLINE);
4328}
4329
4330/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004331static void
paul718e3742002-12-13 20:15:29 +00004332bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4333 struct peer *peer, afi_t afi, safi_t safi)
4334{
4335 struct bgp_filter *filter;
4336 struct peer *g_peer = NULL;
4337 char buf[SU_ADDRSTRLEN];
4338 char *addr;
4339
4340 filter = &peer->filter[afi][safi];
4341 addr = peer->host;
4342 if (peer_group_active (peer))
4343 g_peer = peer->group->conf;
4344
4345 /************************************
4346 ****** Global to the neighbor ******
4347 ************************************/
4348 if (afi == AFI_IP && safi == SAFI_UNICAST)
4349 {
4350 /* remote-as. */
4351 if (! peer_group_active (peer))
4352 {
4353 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4354 vty_out (vty, " neighbor %s peer-group%s", addr,
4355 VTY_NEWLINE);
4356 if (peer->as)
4357 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4358 VTY_NEWLINE);
4359 }
4360 else
4361 {
4362 if (! g_peer->as)
4363 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4364 VTY_NEWLINE);
4365 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4366 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4367 peer->group->name, VTY_NEWLINE);
4368 }
4369
4370 /* local-as. */
4371 if (peer->change_local_as)
4372 if (! peer_group_active (peer))
4373 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4374 peer->change_local_as,
4375 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4376 " no-prepend" : "", VTY_NEWLINE);
4377
4378 /* Description. */
4379 if (peer->desc)
4380 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4381 VTY_NEWLINE);
4382
4383 /* Shutdown. */
4384 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4385 if (! peer_group_active (peer) ||
4386 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4387 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4388
4389 /* BGP port. */
4390 if (peer->port != BGP_PORT_DEFAULT)
4391 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4392 VTY_NEWLINE);
4393
4394 /* Local interface name. */
4395 if (peer->ifname)
4396 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4397 VTY_NEWLINE);
4398
4399 /* Passive. */
4400 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4401 if (! peer_group_active (peer) ||
4402 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4403 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4404
4405 /* EBGP multihop. */
4406 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4407 if (! peer_group_active (peer) ||
4408 g_peer->ttl != peer->ttl)
4409 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4410 VTY_NEWLINE);
4411
hasso6ffd2072005-02-02 14:50:11 +00004412 /* disable-connected-check. */
4413 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004414 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004415 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4416 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004417
4418 /* Update-source. */
4419 if (peer->update_if)
4420 if (! peer_group_active (peer) || ! g_peer->update_if
4421 || strcmp (g_peer->update_if, peer->update_if) != 0)
4422 vty_out (vty, " neighbor %s update-source %s%s", addr,
4423 peer->update_if, VTY_NEWLINE);
4424 if (peer->update_source)
4425 if (! peer_group_active (peer) || ! g_peer->update_source
4426 || sockunion_cmp (g_peer->update_source,
4427 peer->update_source) != 0)
4428 vty_out (vty, " neighbor %s update-source %s%s", addr,
4429 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4430 VTY_NEWLINE);
4431
paul718e3742002-12-13 20:15:29 +00004432 /* advertisement-interval */
4433 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4434 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4435 addr, peer->v_routeadv, VTY_NEWLINE);
4436
4437 /* timers. */
4438 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4439 && ! peer_group_active (peer))
4440 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4441 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4442
4443 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4444 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4445 peer->connect, VTY_NEWLINE);
4446
4447 /* Default weight. */
4448 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4449 if (! peer_group_active (peer) ||
4450 g_peer->weight != peer->weight)
4451 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4452 VTY_NEWLINE);
4453
paul718e3742002-12-13 20:15:29 +00004454 /* Dynamic capability. */
4455 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4456 if (! peer_group_active (peer) ||
4457 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4458 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4459 VTY_NEWLINE);
4460
4461 /* dont capability negotiation. */
4462 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4463 if (! peer_group_active (peer) ||
4464 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4465 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4466 VTY_NEWLINE);
4467
4468 /* override capability negotiation. */
4469 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4470 if (! peer_group_active (peer) ||
4471 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4472 vty_out (vty, " neighbor %s override-capability%s", addr,
4473 VTY_NEWLINE);
4474
4475 /* strict capability negotiation. */
4476 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4477 if (! peer_group_active (peer) ||
4478 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4479 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4480 VTY_NEWLINE);
4481
4482 if (! peer_group_active (peer))
4483 {
4484 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4485 {
4486 if (peer->afc[AFI_IP][SAFI_UNICAST])
4487 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4488 }
4489 else
4490 {
4491 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4492 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4493 }
4494 }
4495 }
4496
4497
4498 /************************************
4499 ****** Per AF to the neighbor ******
4500 ************************************/
4501
4502 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4503 {
4504 if (peer->af_group[afi][safi])
4505 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4506 peer->group->name, VTY_NEWLINE);
4507 else
4508 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4509 }
4510
4511 /* ORF capability. */
4512 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4513 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4514 if (! peer->af_group[afi][safi])
4515 {
4516 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4517
4518 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4519 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4520 vty_out (vty, " both");
4521 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4522 vty_out (vty, " send");
4523 else
4524 vty_out (vty, " receive");
4525 vty_out (vty, "%s", VTY_NEWLINE);
4526 }
4527
4528 /* Route reflector client. */
4529 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4530 && ! peer->af_group[afi][safi])
4531 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4532 VTY_NEWLINE);
4533
4534 /* Nexthop self. */
4535 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4536 && ! peer->af_group[afi][safi])
4537 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4538
4539 /* Remove private AS. */
4540 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4541 && ! peer->af_group[afi][safi])
4542 vty_out (vty, " neighbor %s remove-private-AS%s",
4543 addr, VTY_NEWLINE);
4544
4545 /* send-community print. */
4546 if (! peer->af_group[afi][safi])
4547 {
4548 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4549 {
4550 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4551 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4552 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4553 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4554 vty_out (vty, " neighbor %s send-community extended%s",
4555 addr, VTY_NEWLINE);
4556 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4557 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4558 }
4559 else
4560 {
4561 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4562 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4563 vty_out (vty, " no neighbor %s send-community both%s",
4564 addr, VTY_NEWLINE);
4565 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4566 vty_out (vty, " no neighbor %s send-community extended%s",
4567 addr, VTY_NEWLINE);
4568 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4569 vty_out (vty, " no neighbor %s send-community%s",
4570 addr, VTY_NEWLINE);
4571 }
4572 }
4573
4574 /* Default information */
4575 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4576 && ! peer->af_group[afi][safi])
4577 {
4578 vty_out (vty, " neighbor %s default-originate", addr);
4579 if (peer->default_rmap[afi][safi].name)
4580 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4581 vty_out (vty, "%s", VTY_NEWLINE);
4582 }
4583
4584 /* Soft reconfiguration inbound. */
4585 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4586 if (! peer->af_group[afi][safi] ||
4587 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4588 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4589 VTY_NEWLINE);
4590
4591 /* maximum-prefix. */
4592 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4593 if (! peer->af_group[afi][safi]
4594 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004595 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004596 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4597 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004598 {
hasso0a486e52005-02-01 20:57:17 +00004599 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4600 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4601 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4602 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4603 vty_out (vty, " warning-only");
4604 if (peer->pmax_restart[afi][safi])
4605 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4606 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004607 }
paul718e3742002-12-13 20:15:29 +00004608
4609 /* Route server client. */
4610 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4611 && ! peer->af_group[afi][safi])
4612 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4613
4614 /* Allow AS in. */
4615 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4616 if (! peer_group_active (peer)
4617 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4618 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4619 {
4620 if (peer->allowas_in[afi][safi] == 3)
4621 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4622 else
4623 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4624 peer->allowas_in[afi][safi], VTY_NEWLINE);
4625 }
4626
4627 /* Filter. */
4628 bgp_config_write_filter (vty, peer, afi, safi);
4629
4630 /* atribute-unchanged. */
4631 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4632 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4633 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4634 && ! peer->af_group[afi][safi])
4635 {
4636 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4637 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4638 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4639 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4640 else
4641 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4642 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4643 " as-path" : "",
4644 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4645 " next-hop" : "",
4646 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4647 " med" : "", VTY_NEWLINE);
4648 }
4649}
4650
4651/* Display "address-family" configuration header. */
4652void
4653bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4654 int *write)
4655{
4656 if (*write)
4657 return;
4658
4659 if (afi == AFI_IP && safi == SAFI_UNICAST)
4660 return;
4661
4662 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4663
4664 if (afi == AFI_IP)
4665 {
4666 if (safi == SAFI_MULTICAST)
4667 vty_out (vty, "ipv4 multicast");
4668 else if (safi == SAFI_MPLS_VPN)
4669 vty_out (vty, "vpnv4 unicast");
4670 }
4671 else if (afi == AFI_IP6)
4672 vty_out (vty, "ipv6");
4673
4674 vty_out (vty, "%s", VTY_NEWLINE);
4675
4676 *write = 1;
4677}
4678
4679/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004680static int
paul718e3742002-12-13 20:15:29 +00004681bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4682 safi_t safi)
4683{
4684 int write = 0;
4685 struct peer *peer;
4686 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004687 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004688
4689 bgp_config_write_network (vty, bgp, afi, safi, &write);
4690
4691 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4692
paul1eb8ef22005-04-07 07:30:20 +00004693 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004694 {
4695 if (group->conf->afc[afi][safi])
4696 {
4697 bgp_config_write_family_header (vty, afi, safi, &write);
4698 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4699 }
4700 }
paul1eb8ef22005-04-07 07:30:20 +00004701 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004702 {
4703 if (peer->afc[afi][safi])
4704 {
4705 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4706 {
4707 bgp_config_write_family_header (vty, afi, safi, &write);
4708 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4709 }
4710 }
4711 }
4712 if (write)
4713 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4714
4715 return write;
4716}
4717
4718int
4719bgp_config_write (struct vty *vty)
4720{
4721 int write = 0;
4722 struct bgp *bgp;
4723 struct peer_group *group;
4724 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004725 struct listnode *node, *nnode;
4726 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004727
4728 /* BGP Multiple instance. */
4729 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4730 {
4731 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4732 write++;
4733 }
4734
4735 /* BGP Config type. */
4736 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4737 {
4738 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4739 write++;
4740 }
4741
4742 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004743 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004744 {
4745 if (write)
4746 vty_out (vty, "!%s", VTY_NEWLINE);
4747
4748 /* Router bgp ASN */
4749 vty_out (vty, "router bgp %d", bgp->as);
4750
4751 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4752 {
4753 if (bgp->name)
4754 vty_out (vty, " view %s", bgp->name);
4755 }
4756 vty_out (vty, "%s", VTY_NEWLINE);
4757
4758 /* No Synchronization */
4759 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4760 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4761
4762 /* BGP fast-external-failover. */
4763 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4764 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4765
4766 /* BGP router ID. */
4767 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4768 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4769 VTY_NEWLINE);
4770
paul848973c2003-08-13 00:32:49 +00004771 /* BGP log-neighbor-changes. */
4772 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4773 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4774
paul718e3742002-12-13 20:15:29 +00004775 /* BGP configuration. */
4776 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4777 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4778
4779 /* BGP default ipv4-unicast. */
4780 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4781 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4782
4783 /* BGP default local-preference. */
4784 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4785 vty_out (vty, " bgp default local-preference %d%s",
4786 bgp->default_local_pref, VTY_NEWLINE);
4787
4788 /* BGP client-to-client reflection. */
4789 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4790 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4791
4792 /* BGP cluster ID. */
4793 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4794 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4795 VTY_NEWLINE);
4796
hassoe0701b72004-05-20 09:19:34 +00004797 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004798 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004799 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4800 VTY_NEWLINE);
4801
4802 /* Confederation peer */
4803 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004804 {
hassoe0701b72004-05-20 09:19:34 +00004805 int i;
paul718e3742002-12-13 20:15:29 +00004806
hassoe0701b72004-05-20 09:19:34 +00004807 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004808
hassoe0701b72004-05-20 09:19:34 +00004809 for (i = 0; i < bgp->confed_peers_cnt; i++)
4810 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004811
hassoe0701b72004-05-20 09:19:34 +00004812 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004813 }
4814
4815 /* BGP enforce-first-as. */
4816 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4817 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4818
4819 /* BGP deterministic-med. */
4820 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4821 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004822
4823 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004824 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4825 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4826 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004827 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4828 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4829
paul718e3742002-12-13 20:15:29 +00004830 /* BGP bestpath method. */
4831 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4832 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004833 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4834 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004835 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4836 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4837 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4838 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4839 {
4840 vty_out (vty, " bgp bestpath med");
4841 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4842 vty_out (vty, " confed");
4843 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4844 vty_out (vty, " missing-as-worst");
4845 vty_out (vty, "%s", VTY_NEWLINE);
4846 }
4847
4848 /* BGP network import check. */
4849 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4850 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4851
4852 /* BGP scan interval. */
4853 bgp_config_write_scan_time (vty);
4854
4855 /* BGP flag dampening. */
4856 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4857 BGP_CONFIG_DAMPENING))
4858 bgp_config_write_damp (vty);
4859
4860 /* BGP static route configuration. */
4861 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4862
4863 /* BGP redistribute configuration. */
4864 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4865
4866 /* BGP timers configuration. */
4867 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4868 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4869 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4870 bgp->default_holdtime, VTY_NEWLINE);
4871
4872 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004873 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004874 {
4875 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4876 }
4877
4878 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004879 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004880 {
4881 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4882 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4883 }
4884
4885 /* Distance configuration. */
4886 bgp_config_write_distance (vty, bgp);
4887
4888 /* No auto-summary */
4889 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4890 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4891
4892 /* IPv4 multicast configuration. */
4893 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4894
4895 /* IPv4 VPN configuration. */
4896 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4897
4898 /* IPv6 unicast configuration. */
4899 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4900
4901 write++;
4902 }
4903 return write;
4904}
4905
4906void
paul94f2b392005-06-28 12:44:16 +00004907bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00004908{
4909 memset (&bgp_master, 0, sizeof (struct bgp_master));
4910
4911 bm = &bgp_master;
4912 bm->bgp = list_new ();
4913 bm->port = BGP_PORT_DEFAULT;
4914 bm->master = thread_master_create ();
4915 bm->start_time = time (NULL);
4916}
paul200df112005-06-01 11:17:05 +00004917
paul718e3742002-12-13 20:15:29 +00004918
4919void
paul94f2b392005-06-28 12:44:16 +00004920bgp_init (void)
paul718e3742002-12-13 20:15:29 +00004921{
paul718e3742002-12-13 20:15:29 +00004922 /* BGP VTY commands installation. */
4923 bgp_vty_init ();
4924
4925 /* Create BGP server socket. */
4926 bgp_socket (NULL, bm->port);
4927
4928 /* Init zebra. */
4929 bgp_zebra_init ();
4930
4931 /* BGP inits. */
4932 bgp_attr_init ();
4933 bgp_debug_init ();
4934 bgp_dump_init ();
4935 bgp_route_init ();
4936 bgp_route_map_init ();
4937 bgp_scan_init ();
4938 bgp_mplsvpn_init ();
4939
4940 /* Access list initialize. */
4941 access_list_init ();
4942 access_list_add_hook (peer_distribute_update);
4943 access_list_delete_hook (peer_distribute_update);
4944
4945 /* Filter list initialize. */
4946 bgp_filter_init ();
4947 as_list_add_hook (peer_aslist_update);
4948 as_list_delete_hook (peer_aslist_update);
4949
4950 /* Prefix list initialize.*/
4951 prefix_list_init ();
4952 prefix_list_add_hook (peer_prefix_list_update);
4953 prefix_list_delete_hook (peer_prefix_list_update);
4954
4955 /* Community list initialize. */
4956 bgp_clist = community_list_init ();
4957
4958#ifdef HAVE_SNMP
4959 bgp_snmp_init ();
4960#endif /* HAVE_SNMP */
4961}
paul545acaf2004-04-20 15:13:15 +00004962
4963void
4964bgp_terminate ()
4965{
paul545acaf2004-04-20 15:13:15 +00004966 struct bgp *bgp;
4967 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004968 struct listnode *node, *nnode;
4969 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004970
paul1eb8ef22005-04-07 07:30:20 +00004971 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4972 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00004973 if (peer->status == Established)
4974 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4975 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00004976
paul545acaf2004-04-20 15:13:15 +00004977 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00004978 if (bm->process_main_queue)
4979 work_queue_free (bm->process_main_queue);
4980 if (bm->process_rsclient_queue)
4981 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00004982}
4983