blob: 1f1b4fd2bcfb6501c880bdff4bdaa3c82af2796c [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);
703
704 memset (peer, 0, sizeof (struct peer));
705
706 XFREE (MTYPE_BGP_PEER, peer);
707}
708
709/* increase reference count on a struct peer */
710struct peer *
711peer_lock (struct peer *peer)
712{
713 assert (peer && (peer->lock >= 0));
714
715 peer->lock++;
716
717 return peer;
718}
719
720/* decrease reference count on a struct peer
721 * struct peer is freed and NULL returned if last reference
722 */
723struct peer *
724peer_unlock (struct peer *peer)
725{
726 assert (peer && (peer->lock > 0));
727
728 peer->lock--;
729
730 if (peer->lock == 0)
731 {
732#if 0
733 zlog_debug ("unlocked and freeing");
734 zlog_backtrace (LOG_DEBUG);
735#endif
736 peer_free (peer);
737 return NULL;
738 }
739
740#if 0
741 if (peer->lock == 1)
742 {
743 zlog_debug ("unlocked to 1");
744 zlog_backtrace (LOG_DEBUG);
745 }
746#endif
747
748 return peer;
749}
750
751/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000752static struct peer *
753peer_new ()
754{
755 afi_t afi;
756 safi_t safi;
757 struct peer *peer;
758 struct servent *sp;
759
760 /* Allocate new peer. */
761 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
762 memset (peer, 0, sizeof (struct peer));
763
764 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000765 peer->fd = -1;
paul200df112005-06-01 11:17:05 +0000766 peer->lock = 1;
paul718e3742002-12-13 20:15:29 +0000767 peer->v_start = BGP_INIT_START_TIMER;
768 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
769 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
770 peer->status = Idle;
771 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000772 peer->weight = 0;
773
774 /* Set default flags. */
775 for (afi = AFI_IP; afi < AFI_MAX; afi++)
776 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
777 {
778 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
779 {
780 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
781 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
782 }
783 peer->orf_plist[afi][safi] = NULL;
784 }
785 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
786
787 /* Create buffers. */
788 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
789 peer->obuf = stream_fifo_new ();
790 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
791
792 bgp_sync_init (peer);
793
794 /* Get service port number. */
795 sp = getservbyname ("bgp", "tcp");
796 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
797
798 return peer;
799}
800
801/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000802static struct peer *
paul718e3742002-12-13 20:15:29 +0000803peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
804 as_t remote_as, afi_t afi, safi_t safi)
805{
806 int active;
807 struct peer *peer;
808 char buf[SU_ADDRSTRLEN];
809
810 peer = peer_new ();
811 peer->bgp = bgp;
812 peer->su = *su;
813 peer->local_as = local_as;
814 peer->as = remote_as;
815 peer->local_id = bgp->router_id;
816 peer->v_holdtime = bgp->default_holdtime;
817 peer->v_keepalive = bgp->default_keepalive;
818 if (peer_sort (peer) == BGP_PEER_IBGP)
819 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
820 else
821 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000822
823 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000824 listnode_add_sort (bgp->peer, peer);
825
826 active = peer_active (peer);
827
828 if (afi && safi)
829 peer->afc[afi][safi] = 1;
830
831 /* Last read time set */
832 peer->readtime = time (NULL);
833
paul848973c2003-08-13 00:32:49 +0000834 /* Last reset time set */
835 peer->resettime = time (NULL);
836
paul718e3742002-12-13 20:15:29 +0000837 /* Default TTL set. */
838 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
839
840 /* Make peer's address string. */
841 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000842 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000843
844 /* Set up peer's events and timers. */
845 if (! active && peer_active (peer))
846 bgp_timer_set (peer);
847
848 return peer;
849}
850
pauleb821182004-05-01 08:44:08 +0000851/* Make accept BGP peer. Called from bgp_accept (). */
852struct peer *
853peer_create_accept (struct bgp *bgp)
854{
855 struct peer *peer;
856
857 peer = peer_new ();
858 peer->bgp = bgp;
paul200df112005-06-01 11:17:05 +0000859
860 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000861 listnode_add_sort (bgp->peer, peer);
862
863 return peer;
864}
865
paul718e3742002-12-13 20:15:29 +0000866/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000867static void
paul718e3742002-12-13 20:15:29 +0000868peer_as_change (struct peer *peer, as_t as)
869{
870 int type;
871
872 /* Stop peer. */
873 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
874 {
875 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000876 {
877 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
878 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
879 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
880 }
paul718e3742002-12-13 20:15:29 +0000881 else
882 BGP_EVENT_ADD (peer, BGP_Stop);
883 }
884 type = peer_sort (peer);
885 peer->as = as;
886
paul848973c2003-08-13 00:32:49 +0000887 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
888 && ! bgp_confederation_peers_check (peer->bgp, as)
889 && peer->bgp->as != as)
890 peer->local_as = peer->bgp->confed_id;
891 else
892 peer->local_as = peer->bgp->as;
893
paul718e3742002-12-13 20:15:29 +0000894 /* Advertisement-interval reset */
895 if (peer_sort (peer) == BGP_PEER_IBGP)
896 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
897 else
898 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
899
900 /* TTL reset */
901 if (peer_sort (peer) == BGP_PEER_IBGP)
902 peer->ttl = 255;
903 else if (type == BGP_PEER_IBGP)
904 peer->ttl = 1;
905
906 /* reflector-client reset */
907 if (peer_sort (peer) != BGP_PEER_IBGP)
908 {
909 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
910 PEER_FLAG_REFLECTOR_CLIENT);
911 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
912 PEER_FLAG_REFLECTOR_CLIENT);
913 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
914 PEER_FLAG_REFLECTOR_CLIENT);
915 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
916 PEER_FLAG_REFLECTOR_CLIENT);
917 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
918 PEER_FLAG_REFLECTOR_CLIENT);
919 }
920
921 /* local-as reset */
922 if (peer_sort (peer) != BGP_PEER_EBGP)
923 {
924 peer->change_local_as = 0;
925 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
926 }
927}
928
929/* If peer does not exist, create new one. If peer already exists,
930 set AS number to the peer. */
931int
932peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
933 afi_t afi, safi_t safi)
934{
935 struct peer *peer;
936 as_t local_as;
937
938 peer = peer_lookup (bgp, su);
939
940 if (peer)
941 {
942 /* When this peer is a member of peer-group. */
943 if (peer->group)
944 {
945 if (peer->group->conf->as)
946 {
947 /* Return peer group's AS number. */
948 *as = peer->group->conf->as;
949 return BGP_ERR_PEER_GROUP_MEMBER;
950 }
951 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
952 {
953 if (bgp->as != *as)
954 {
955 *as = peer->as;
956 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
957 }
958 }
959 else
960 {
961 if (bgp->as == *as)
962 {
963 *as = peer->as;
964 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
965 }
966 }
967 }
968
969 /* Existing peer's AS number change. */
970 if (peer->as != *as)
971 peer_as_change (peer, *as);
972 }
973 else
974 {
975
976 /* If the peer is not part of our confederation, and its not an
977 iBGP peer then spoof the source AS */
978 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
979 && ! bgp_confederation_peers_check (bgp, *as)
980 && bgp->as != *as)
981 local_as = bgp->confed_id;
982 else
983 local_as = bgp->as;
984
985 /* If this is IPv4 unicast configuration and "no bgp default
986 ipv4-unicast" is specified. */
987
988 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
989 && afi == AFI_IP && safi == SAFI_UNICAST)
990 peer = peer_create (su, bgp, local_as, *as, 0, 0);
991 else
992 peer = peer_create (su, bgp, local_as, *as, afi, safi);
993 }
994
995 return 0;
996}
997
998/* Activate the peer or peer group for specified AFI and SAFI. */
999int
1000peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1001{
1002 int active;
1003
1004 if (peer->afc[afi][safi])
1005 return 0;
1006
1007 /* Activate the address family configuration. */
1008 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1009 peer->afc[afi][safi] = 1;
1010 else
1011 {
1012 active = peer_active (peer);
1013
1014 peer->afc[afi][safi] = 1;
1015
1016 if (! active && peer_active (peer))
1017 bgp_timer_set (peer);
1018 else
1019 {
1020 if (peer->status == Established)
1021 {
1022 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1023 {
1024 peer->afc_adv[afi][safi] = 1;
1025 bgp_capability_send (peer, afi, safi,
1026 CAPABILITY_CODE_MP,
1027 CAPABILITY_ACTION_SET);
1028 if (peer->afc_recv[afi][safi])
1029 {
1030 peer->afc_nego[afi][safi] = 1;
1031 bgp_announce_route (peer, afi, safi);
1032 }
1033 }
1034 else
hassoe0701b72004-05-20 09:19:34 +00001035 {
1036 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1037 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1038 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1039 }
paul718e3742002-12-13 20:15:29 +00001040 }
1041 }
1042 }
1043 return 0;
1044}
1045
1046int
1047peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1048{
1049 struct peer_group *group;
1050 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001051 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001052
1053 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1054 {
1055 group = peer->group;
1056
paul1eb8ef22005-04-07 07:30:20 +00001057 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001058 {
1059 if (peer1->af_group[afi][safi])
1060 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1061 }
1062 }
1063 else
1064 {
1065 if (peer->af_group[afi][safi])
1066 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1067 }
1068
1069 if (! peer->afc[afi][safi])
1070 return 0;
1071
1072 /* De-activate the address family configuration. */
1073 peer->afc[afi][safi] = 0;
1074 peer_af_flag_reset (peer, afi, safi);
1075
1076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1077 {
1078 if (peer->status == Established)
1079 {
1080 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1081 {
1082 peer->afc_adv[afi][safi] = 0;
1083 peer->afc_nego[afi][safi] = 0;
1084
1085 if (peer_active_nego (peer))
1086 {
1087 bgp_capability_send (peer, afi, safi,
1088 CAPABILITY_CODE_MP,
1089 CAPABILITY_ACTION_UNSET);
1090 bgp_clear_route (peer, afi, safi);
1091 peer->pcount[afi][safi] = 0;
1092 }
1093 else
hassoe0701b72004-05-20 09:19:34 +00001094 {
1095 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1096 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1097 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1098 }
paul718e3742002-12-13 20:15:29 +00001099 }
1100 else
hassoe0701b72004-05-20 09:19:34 +00001101 {
1102 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1103 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1104 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1105 }
paul718e3742002-12-13 20:15:29 +00001106 }
1107 }
1108 return 0;
1109}
1110
hasso93406d82005-02-02 14:40:33 +00001111void
1112peer_nsf_stop (struct peer *peer)
1113{
1114 afi_t afi;
1115 safi_t safi;
1116
1117 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1118 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1119
1120 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1121 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1122 peer->nsf[afi][safi] = 0;
1123
1124 if (peer->t_gr_restart)
1125 {
1126 BGP_TIMER_OFF (peer->t_gr_restart);
1127 if (BGP_DEBUG (events, EVENTS))
1128 zlog_debug ("%s graceful restart timer stopped", peer->host);
1129 }
1130 if (peer->t_gr_stale)
1131 {
1132 BGP_TIMER_OFF (peer->t_gr_stale);
1133 if (BGP_DEBUG (events, EVENTS))
1134 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1135 }
1136 bgp_clear_route_all (peer);
1137}
1138
paul718e3742002-12-13 20:15:29 +00001139/* Delete peer from confguration. */
1140int
1141peer_delete (struct peer *peer)
1142{
1143 int i;
1144 afi_t afi;
1145 safi_t safi;
1146 struct bgp *bgp;
1147 struct bgp_filter *filter;
1148
1149 bgp = peer->bgp;
1150
hasso93406d82005-02-02 14:40:33 +00001151 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1152 peer_nsf_stop (peer);
1153
paul718e3742002-12-13 20:15:29 +00001154 /* If this peer belongs to peer group. Clearn up the
1155 relationship. */
1156 if (peer->group)
1157 {
paul200df112005-06-01 11:17:05 +00001158 peer = peer_unlock (peer); /* peer-group reference */
paul718e3742002-12-13 20:15:29 +00001159 listnode_delete (peer->group->peer, peer);
1160 peer->group = NULL;
1161 }
paul200df112005-06-01 11:17:05 +00001162
paul718e3742002-12-13 20:15:29 +00001163 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001164 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1165 * executed after peer structure is deleted.
1166 */
hassoe0701b72004-05-20 09:19:34 +00001167 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001168 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001169 bgp_fsm_change_status (peer, Idle); /* stops all timers */
1170
1171 /* Stop all timers - should already have been done in bgp_stop */
paul718e3742002-12-13 20:15:29 +00001172 BGP_TIMER_OFF (peer->t_start);
1173 BGP_TIMER_OFF (peer->t_connect);
1174 BGP_TIMER_OFF (peer->t_holdtime);
1175 BGP_TIMER_OFF (peer->t_keepalive);
1176 BGP_TIMER_OFF (peer->t_asorig);
1177 BGP_TIMER_OFF (peer->t_routeadv);
hasso0a486e52005-02-01 20:57:17 +00001178 BGP_TIMER_OFF (peer->t_pmax_restart);
hasso93406d82005-02-02 14:40:33 +00001179 BGP_TIMER_OFF (peer->t_gr_restart);
1180 BGP_TIMER_OFF (peer->t_gr_stale);
paul718e3742002-12-13 20:15:29 +00001181
1182 /* Delete from all peer list. */
1183 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001184 {
paul200df112005-06-01 11:17:05 +00001185 peer_unlock (peer); /* bgp peer list reference */
1186 listnode_delete (bgp->peer, peer);
1187
paulfee0f4c2004-09-13 05:12:46 +00001188 if (peer_rsclient_active (peer))
paul200df112005-06-01 11:17:05 +00001189 {
1190 peer_unlock (peer); /* rsclient list reference */
1191 listnode_delete (bgp->rsclient, peer);
1192 }
paulfee0f4c2004-09-13 05:12:46 +00001193 }
1194
1195 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1196 member of a peer_group. */
1197 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1198 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1199 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1200 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001201
paul200df112005-06-01 11:17:05 +00001202 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001203 if (peer->ibuf)
1204 stream_free (peer->ibuf);
paul200df112005-06-01 11:17:05 +00001205
paul718e3742002-12-13 20:15:29 +00001206 if (peer->obuf)
1207 stream_fifo_free (peer->obuf);
1208
1209 if (peer->work)
1210 stream_free (peer->work);
paul200df112005-06-01 11:17:05 +00001211
paul718e3742002-12-13 20:15:29 +00001212 /* Local and remote addresses. */
1213 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001214 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001215 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001216 sockunion_free (peer->su_remote);
paul200df112005-06-01 11:17:05 +00001217
paul718e3742002-12-13 20:15:29 +00001218 bgp_sync_delete (peer);
1219
1220 /* Free filter related memory. */
1221 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1222 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1223 {
1224 filter = &peer->filter[afi][safi];
1225
1226 for (i = FILTER_IN; i < FILTER_MAX; i++)
1227 {
1228 if (filter->dlist[i].name)
1229 free (filter->dlist[i].name);
1230 if (filter->plist[i].name)
1231 free (filter->plist[i].name);
1232 if (filter->aslist[i].name)
1233 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001234
1235 filter->dlist[i].name = NULL;
1236 filter->plist[i].name = NULL;
1237 filter->aslist[i].name = NULL;
1238 }
1239 for (i = RMAP_IN; i < RMAP_MAX; i++)
1240 {
paul718e3742002-12-13 20:15:29 +00001241 if (filter->map[i].name)
1242 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001243 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001244 }
1245
1246 if (filter->usmap.name)
1247 free (filter->usmap.name);
1248
1249 if (peer->default_rmap[afi][safi].name)
1250 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001251
1252 filter->usmap.name = NULL;
1253 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001254 }
paul200df112005-06-01 11:17:05 +00001255
1256 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001257
1258 return 0;
1259}
1260
paul94f2b392005-06-28 12:44:16 +00001261static int
paul718e3742002-12-13 20:15:29 +00001262peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1263{
1264 return strcmp (g1->name, g2->name);
1265}
1266
1267/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001268static int
paul718e3742002-12-13 20:15:29 +00001269peer_group_active (struct peer *peer)
1270{
1271 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1272 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1273 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1274 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1275 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1276 return 1;
1277 return 0;
1278}
1279
1280/* Peer group cofiguration. */
1281static struct peer_group *
1282peer_group_new ()
1283{
1284 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1285 sizeof (struct peer_group));
1286}
1287
paul94f2b392005-06-28 12:44:16 +00001288static void
paul718e3742002-12-13 20:15:29 +00001289peer_group_free (struct peer_group *group)
1290{
1291 XFREE (MTYPE_PEER_GROUP, group);
1292}
1293
1294struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001295peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001296{
1297 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001298 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001299
paul1eb8ef22005-04-07 07:30:20 +00001300 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001301 {
1302 if (strcmp (group->name, name) == 0)
1303 return group;
1304 }
1305 return NULL;
1306}
1307
1308struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001309peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001310{
1311 struct peer_group *group;
1312
1313 group = peer_group_lookup (bgp, name);
1314 if (group)
1315 return group;
1316
1317 group = peer_group_new ();
1318 group->bgp = bgp;
1319 group->name = strdup (name);
1320 group->peer = list_new ();
1321 group->conf = peer_new ();
1322 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1323 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1324 group->conf->host = strdup (name);
1325 group->conf->bgp = bgp;
1326 group->conf->group = group;
1327 group->conf->as = 0;
1328 group->conf->ttl = 1;
1329 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1330 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1331 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1332 group->conf->keepalive = 0;
1333 group->conf->holdtime = 0;
1334 group->conf->connect = 0;
1335 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1336 listnode_add_sort (bgp->group, group);
1337
1338 return 0;
1339}
1340
paul94f2b392005-06-28 12:44:16 +00001341static void
paul718e3742002-12-13 20:15:29 +00001342peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1343 afi_t afi, safi_t safi)
1344{
1345 int in = FILTER_IN;
1346 int out = FILTER_OUT;
1347 struct peer *conf;
1348 struct bgp_filter *pfilter;
1349 struct bgp_filter *gfilter;
1350
1351 conf = group->conf;
1352 pfilter = &peer->filter[afi][safi];
1353 gfilter = &conf->filter[afi][safi];
1354
1355 /* remote-as */
1356 if (conf->as)
1357 peer->as = conf->as;
1358
1359 /* remote-as */
1360 if (conf->change_local_as)
1361 peer->change_local_as = conf->change_local_as;
1362
1363 /* TTL */
1364 peer->ttl = conf->ttl;
1365
1366 /* Weight */
1367 peer->weight = conf->weight;
1368
1369 /* peer flags apply */
1370 peer->flags = conf->flags;
1371 /* peer af_flags apply */
1372 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1373 /* peer config apply */
1374 peer->config = conf->config;
1375
1376 /* peer timers apply */
1377 peer->holdtime = conf->holdtime;
1378 peer->keepalive = conf->keepalive;
1379 peer->connect = conf->connect;
1380 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1381 peer->v_connect = conf->connect;
1382 else
1383 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1384
1385 /* advertisement-interval reset */
1386 if (peer_sort (peer) == BGP_PEER_IBGP)
1387 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1388 else
1389 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1390
1391 /* maximum-prefix */
1392 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001393 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001394 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001395
1396 /* allowas-in */
1397 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1398
paulfee0f4c2004-09-13 05:12:46 +00001399 /* route-server-client */
1400 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1401 {
1402 /* Make peer's RIB point to group's RIB. */
1403 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1404
1405 /* Import policy. */
1406 if (pfilter->map[RMAP_IMPORT].name)
1407 free (pfilter->map[RMAP_IMPORT].name);
1408 if (gfilter->map[RMAP_IMPORT].name)
1409 {
1410 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1411 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1412 }
1413 else
1414 {
1415 pfilter->map[RMAP_IMPORT].name = NULL;
1416 pfilter->map[RMAP_IMPORT].map = NULL;
1417 }
1418
1419 /* Export policy. */
1420 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1421 {
1422 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1423 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1424 }
1425 }
1426
paul718e3742002-12-13 20:15:29 +00001427 /* default-originate route-map */
1428 if (conf->default_rmap[afi][safi].name)
1429 {
1430 if (peer->default_rmap[afi][safi].name)
1431 free (peer->default_rmap[afi][safi].name);
1432 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1433 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1434 }
1435
1436 /* update-source apply */
1437 if (conf->update_source)
1438 {
1439 if (peer->update_source)
1440 sockunion_free (peer->update_source);
1441 if (peer->update_if)
1442 {
1443 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1444 peer->update_if = NULL;
1445 }
1446 peer->update_source = sockunion_dup (conf->update_source);
1447 }
1448 else if (conf->update_if)
1449 {
1450 if (peer->update_if)
1451 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1452 if (peer->update_source)
1453 {
1454 sockunion_free (peer->update_source);
1455 peer->update_source = NULL;
1456 }
1457 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1458 }
1459
1460 /* inbound filter apply */
1461 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1462 {
1463 if (pfilter->dlist[in].name)
1464 free (pfilter->dlist[in].name);
1465 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1466 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1467 }
1468 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1469 {
1470 if (pfilter->plist[in].name)
1471 free (pfilter->plist[in].name);
1472 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1473 pfilter->plist[in].plist = gfilter->plist[in].plist;
1474 }
1475 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1476 {
1477 if (pfilter->aslist[in].name)
1478 free (pfilter->aslist[in].name);
1479 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1480 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1481 }
paulfee0f4c2004-09-13 05:12:46 +00001482 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001483 {
paulfee0f4c2004-09-13 05:12:46 +00001484 if (pfilter->map[RMAP_IN].name)
1485 free (pfilter->map[RMAP_IN].name);
1486 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1487 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001488 }
1489
1490 /* outbound filter apply */
1491 if (gfilter->dlist[out].name)
1492 {
1493 if (pfilter->dlist[out].name)
1494 free (pfilter->dlist[out].name);
1495 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1496 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1497 }
1498 else
1499 {
1500 if (pfilter->dlist[out].name)
1501 free (pfilter->dlist[out].name);
1502 pfilter->dlist[out].name = NULL;
1503 pfilter->dlist[out].alist = NULL;
1504 }
1505 if (gfilter->plist[out].name)
1506 {
1507 if (pfilter->plist[out].name)
1508 free (pfilter->plist[out].name);
1509 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1510 pfilter->plist[out].plist = gfilter->plist[out].plist;
1511 }
1512 else
1513 {
1514 if (pfilter->plist[out].name)
1515 free (pfilter->plist[out].name);
1516 pfilter->plist[out].name = NULL;
1517 pfilter->plist[out].plist = NULL;
1518 }
1519 if (gfilter->aslist[out].name)
1520 {
1521 if (pfilter->aslist[out].name)
1522 free (pfilter->aslist[out].name);
1523 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1524 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1525 }
1526 else
1527 {
1528 if (pfilter->aslist[out].name)
1529 free (pfilter->aslist[out].name);
1530 pfilter->aslist[out].name = NULL;
1531 pfilter->aslist[out].aslist = NULL;
1532 }
paulfee0f4c2004-09-13 05:12:46 +00001533 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001534 {
paulfee0f4c2004-09-13 05:12:46 +00001535 if (pfilter->map[RMAP_OUT].name)
1536 free (pfilter->map[RMAP_OUT].name);
1537 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1538 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001539 }
1540 else
1541 {
paulfee0f4c2004-09-13 05:12:46 +00001542 if (pfilter->map[RMAP_OUT].name)
1543 free (pfilter->map[RMAP_OUT].name);
1544 pfilter->map[RMAP_OUT].name = NULL;
1545 pfilter->map[RMAP_OUT].map = NULL;
1546 }
1547
1548 /* RS-client's import/export route-maps. */
1549 if (gfilter->map[RMAP_IMPORT].name)
1550 {
1551 if (pfilter->map[RMAP_IMPORT].name)
1552 free (pfilter->map[RMAP_IMPORT].name);
1553 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1554 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1555 }
1556 else
1557 {
1558 if (pfilter->map[RMAP_IMPORT].name)
1559 free (pfilter->map[RMAP_IMPORT].name);
1560 pfilter->map[RMAP_IMPORT].name = NULL;
1561 pfilter->map[RMAP_IMPORT].map = NULL;
1562 }
1563 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1564 {
1565 if (pfilter->map[RMAP_EXPORT].name)
1566 free (pfilter->map[RMAP_EXPORT].name);
1567 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1568 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001569 }
1570
1571 if (gfilter->usmap.name)
1572 {
1573 if (pfilter->usmap.name)
1574 free (pfilter->usmap.name);
1575 pfilter->usmap.name = strdup (gfilter->usmap.name);
1576 pfilter->usmap.map = gfilter->usmap.map;
1577 }
1578 else
1579 {
1580 if (pfilter->usmap.name)
1581 free (pfilter->usmap.name);
1582 pfilter->usmap.name = NULL;
1583 pfilter->usmap.map = NULL;
1584 }
1585}
1586
1587/* Peer group's remote AS configuration. */
1588int
paulfd79ac92004-10-13 05:06:08 +00001589peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001590{
1591 struct peer_group *group;
1592 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001593 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001594
1595 group = peer_group_lookup (bgp, group_name);
1596 if (! group)
1597 return -1;
1598
1599 if (group->conf->as == *as)
1600 return 0;
1601
1602 /* When we setup peer-group AS number all peer group member's AS
1603 number must be updated to same number. */
1604 peer_as_change (group->conf, *as);
1605
paul1eb8ef22005-04-07 07:30:20 +00001606 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001607 {
1608 if (peer->as != *as)
1609 peer_as_change (peer, *as);
1610 }
1611
1612 return 0;
1613}
1614
1615int
1616peer_group_delete (struct peer_group *group)
1617{
1618 struct bgp *bgp;
1619 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001620 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001621
1622 bgp = group->bgp;
1623
paul1eb8ef22005-04-07 07:30:20 +00001624 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001625 {
1626 peer->group = NULL;
1627 peer_delete (peer);
1628 }
1629 list_delete (group->peer);
1630
1631 free (group->name);
1632 group->name = NULL;
1633
1634 group->conf->group = NULL;
1635 peer_delete (group->conf);
1636
1637 /* Delete from all peer_group list. */
1638 listnode_delete (bgp->group, group);
1639
1640 peer_group_free (group);
1641
1642 return 0;
1643}
1644
1645int
1646peer_group_remote_as_delete (struct peer_group *group)
1647{
1648 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001649 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001650
1651 if (! group->conf->as)
1652 return 0;
1653
paul1eb8ef22005-04-07 07:30:20 +00001654 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001655 {
1656 peer->group = NULL;
1657 peer_delete (peer);
1658 }
1659 list_delete_all_node (group->peer);
1660
1661 group->conf->as = 0;
1662
1663 return 0;
1664}
1665
1666/* Bind specified peer to peer group. */
1667int
1668peer_group_bind (struct bgp *bgp, union sockunion *su,
1669 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1670{
1671 struct peer *peer;
1672 int first_member = 0;
1673
1674 /* Check peer group's address family. */
1675 if (! group->conf->afc[afi][safi])
1676 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1677
1678 /* Lookup the peer. */
1679 peer = peer_lookup (bgp, su);
1680
1681 /* Create a new peer. */
1682 if (! peer)
1683 {
1684 if (! group->conf->as)
1685 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1686
1687 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1688 peer->group = group;
1689 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001690
1691 peer = peer_lock (peer); /* peer-group group->peer reference */
paul718e3742002-12-13 20:15:29 +00001692 listnode_add (group->peer, peer);
1693 peer_group2peer_config_copy (group, peer, afi, safi);
1694
1695 return 0;
1696 }
1697
1698 /* When the peer already belongs to peer group, check the consistency. */
1699 if (peer->af_group[afi][safi])
1700 {
1701 if (strcmp (peer->group->name, group->name) != 0)
1702 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1703
1704 return 0;
1705 }
1706
1707 /* Check current peer group configuration. */
1708 if (peer_group_active (peer)
1709 && strcmp (peer->group->name, group->name) != 0)
1710 return BGP_ERR_PEER_GROUP_MISMATCH;
1711
1712 if (! group->conf->as)
1713 {
1714 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1715 && peer_sort (group->conf) != peer_sort (peer))
1716 {
1717 if (as)
1718 *as = peer->as;
1719 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1720 }
1721
1722 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1723 first_member = 1;
1724 }
1725
1726 peer->af_group[afi][safi] = 1;
1727 peer->afc[afi][safi] = 1;
1728 if (! peer->group)
1729 {
1730 peer->group = group;
paul200df112005-06-01 11:17:05 +00001731
1732 peer = peer_lock (peer); /* peer-group group->peer reference */
paul718e3742002-12-13 20:15:29 +00001733 listnode_add (group->peer, peer);
1734 }
1735
1736 if (first_member)
1737 {
1738 /* Advertisement-interval reset */
1739 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1740 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1741 else
1742 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1743
1744 /* ebgp-multihop reset */
1745 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1746 group->conf->ttl = 255;
1747
1748 /* local-as reset */
1749 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1750 {
1751 group->conf->change_local_as = 0;
1752 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1753 }
1754 }
paulfee0f4c2004-09-13 05:12:46 +00001755
1756 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1757 {
1758 /* If it's not configured as RSERVER_CLIENT in any other address
1759 family, without being member of a peer_group, remove it from
1760 list bgp->rsclient.*/
1761 if (! peer_rsclient_active (peer))
paul200df112005-06-01 11:17:05 +00001762 {
1763 peer_unlock (peer); /* peer rsclient reference */
1764 listnode_delete (bgp->rsclient, peer);
1765 }
paulfee0f4c2004-09-13 05:12:46 +00001766
1767 bgp_table_finish (peer->rib[afi][safi]);
1768
1769 /* Import policy. */
1770 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1771 {
1772 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1773 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1774 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1775 }
1776
1777 /* Export policy. */
1778 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1779 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1780 {
1781 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1782 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1783 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1784 }
1785 }
1786
paul718e3742002-12-13 20:15:29 +00001787 peer_group2peer_config_copy (group, peer, afi, safi);
1788
1789 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001790 {
1791 peer->last_reset = PEER_DOWN_RMAP_BIND;
1792 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1793 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1794 }
paul718e3742002-12-13 20:15:29 +00001795 else
1796 BGP_EVENT_ADD (peer, BGP_Stop);
1797
1798 return 0;
1799}
1800
1801int
1802peer_group_unbind (struct bgp *bgp, struct peer *peer,
1803 struct peer_group *group, afi_t afi, safi_t safi)
1804{
1805 if (! peer->af_group[afi][safi])
1806 return 0;
1807
1808 if (group != peer->group)
1809 return BGP_ERR_PEER_GROUP_MISMATCH;
1810
1811 peer->af_group[afi][safi] = 0;
1812 peer->afc[afi][safi] = 0;
1813 peer_af_flag_reset (peer, afi, safi);
1814
paulfee0f4c2004-09-13 05:12:46 +00001815 if (peer->rib[afi][safi])
1816 peer->rib[afi][safi] = NULL;
1817
paul718e3742002-12-13 20:15:29 +00001818 if (! peer_group_active (peer))
1819 {
paul200df112005-06-01 11:17:05 +00001820 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001821 listnode_delete (group->peer, peer);
1822 peer->group = NULL;
1823 if (group->conf->as)
1824 {
1825 peer_delete (peer);
1826 return 0;
1827 }
1828 peer_global_config_reset (peer);
1829 }
1830
1831 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001832 {
1833 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1834 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1835 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1836 }
paul718e3742002-12-13 20:15:29 +00001837 else
1838 BGP_EVENT_ADD (peer, BGP_Stop);
1839
1840 return 0;
1841}
1842
1843/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001844static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001845bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001846{
1847 struct bgp *bgp;
1848 afi_t afi;
1849 safi_t safi;
1850
paul200df112005-06-01 11:17:05 +00001851 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1852 return NULL;
1853
paul718e3742002-12-13 20:15:29 +00001854 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001855 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001856
1857 bgp->peer = list_new ();
1858 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1859
1860 bgp->group = list_new ();
1861 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1862
paulfee0f4c2004-09-13 05:12:46 +00001863 bgp->rsclient = list_new ();
1864 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1865
paul718e3742002-12-13 20:15:29 +00001866 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1867 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1868 {
1869 bgp->route[afi][safi] = bgp_table_init ();
1870 bgp->aggregate[afi][safi] = bgp_table_init ();
1871 bgp->rib[afi][safi] = bgp_table_init ();
1872 }
1873
1874 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1875 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1876 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001877 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1878 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001879
1880 bgp->as = *as;
1881
1882 if (name)
1883 bgp->name = strdup (name);
1884
1885 return bgp;
1886}
1887
1888/* Return first entry of BGP. */
1889struct bgp *
paul94f2b392005-06-28 12:44:16 +00001890bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001891{
1892 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001893 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001894 return NULL;
1895}
1896
1897/* Lookup BGP entry. */
1898struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001899bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001900{
1901 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001902 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001903
paul1eb8ef22005-04-07 07:30:20 +00001904 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001905 if (bgp->as == as
1906 && ((bgp->name == NULL && name == NULL)
1907 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1908 return bgp;
1909 return NULL;
1910}
1911
1912/* Lookup BGP structure by view name. */
1913struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001914bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001915{
1916 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001917 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001918
paul1eb8ef22005-04-07 07:30:20 +00001919 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001920 if ((bgp->name == NULL && name == NULL)
1921 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1922 return bgp;
1923 return NULL;
1924}
1925
1926/* Called from VTY commands. */
1927int
paulfd79ac92004-10-13 05:06:08 +00001928bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001929{
1930 struct bgp *bgp;
1931
1932 /* Multiple instance check. */
1933 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1934 {
1935 if (name)
1936 bgp = bgp_lookup_by_name (name);
1937 else
1938 bgp = bgp_get_default ();
1939
1940 /* Already exists. */
1941 if (bgp)
1942 {
1943 if (bgp->as != *as)
1944 {
1945 *as = bgp->as;
1946 return BGP_ERR_INSTANCE_MISMATCH;
1947 }
1948 *bgp_val = bgp;
1949 return 0;
1950 }
1951 }
1952 else
1953 {
1954 /* BGP instance name can not be specified for single instance. */
1955 if (name)
1956 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1957
1958 /* Get default BGP structure if exists. */
1959 bgp = bgp_get_default ();
1960
1961 if (bgp)
1962 {
1963 if (bgp->as != *as)
1964 {
1965 *as = bgp->as;
1966 return BGP_ERR_AS_MISMATCH;
1967 }
1968 *bgp_val = bgp;
1969 return 0;
1970 }
1971 }
1972
1973 bgp = bgp_create (as, name);
1974 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001975 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001976 *bgp_val = bgp;
1977
1978 return 0;
1979}
1980
1981/* Delete BGP instance. */
1982int
1983bgp_delete (struct bgp *bgp)
1984{
1985 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00001986 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001987 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001988 struct listnode *next;
1989 afi_t afi;
1990 safi_t safi;
1991 int i;
1992
1993 /* Delete static route. */
1994 bgp_static_delete (bgp);
1995
1996 /* Unset redistribution. */
1997 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1998 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1999 if (i != ZEBRA_ROUTE_BGP)
2000 bgp_redistribute_unset (bgp, afi, i);
2001
hassob6b7cff2005-05-26 08:29:07 +00002002 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2003 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002004 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002005
paul1eb8ef22005-04-07 07:30:20 +00002006 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2007 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002008 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002009
hasso54a6ed32005-05-26 22:12:33 +00002010 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2011 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002012 list_delete (bgp->rsclient);
2013
paul718e3742002-12-13 20:15:29 +00002014 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002015
paul718e3742002-12-13 20:15:29 +00002016 if (bgp->name)
2017 free (bgp->name);
2018
2019 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2020 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2021 {
2022 if (bgp->route[afi][safi])
2023 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2024 if (bgp->aggregate[afi][safi])
2025 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2026 if (bgp->rib[afi][safi])
2027 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2028 }
2029 XFREE (MTYPE_BGP, bgp);
2030
2031 return 0;
2032}
2033
2034struct peer *
2035peer_lookup (struct bgp *bgp, union sockunion *su)
2036{
2037 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002038 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002039
2040 if (! bgp)
2041 bgp = bgp_get_default ();
2042
2043 if (! bgp)
2044 return NULL;
2045
paul1eb8ef22005-04-07 07:30:20 +00002046 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002047 {
pauleb821182004-05-01 08:44:08 +00002048 if (sockunion_same (&peer->su, su)
2049 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2050 return peer;
paul718e3742002-12-13 20:15:29 +00002051 }
2052 return NULL;
2053}
2054
2055struct peer *
2056peer_lookup_with_open (union sockunion *su, as_t remote_as,
2057 struct in_addr *remote_id, int *as)
2058{
2059 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002060 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002061 struct bgp *bgp;
2062
2063 bgp = bgp_get_default ();
2064 if (! bgp)
2065 return NULL;
2066
paul1eb8ef22005-04-07 07:30:20 +00002067 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002068 {
pauleb821182004-05-01 08:44:08 +00002069 if (sockunion_same (&peer->su, su)
2070 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2071 {
2072 if (peer->as == remote_as
2073 && peer->remote_id.s_addr == remote_id->s_addr)
2074 return peer;
2075 if (peer->as == remote_as)
2076 *as = 1;
2077 }
paul718e3742002-12-13 20:15:29 +00002078 }
paul1eb8ef22005-04-07 07:30:20 +00002079 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002080 {
pauleb821182004-05-01 08:44:08 +00002081 if (sockunion_same (&peer->su, su)
2082 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2083 {
2084 if (peer->as == remote_as
2085 && peer->remote_id.s_addr == 0)
2086 return peer;
2087 if (peer->as == remote_as)
2088 *as = 1;
2089 }
paul718e3742002-12-13 20:15:29 +00002090 }
2091 return NULL;
2092}
2093
2094/* If peer is configured at least one address family return 1. */
2095int
2096peer_active (struct peer *peer)
2097{
2098 if (peer->afc[AFI_IP][SAFI_UNICAST]
2099 || peer->afc[AFI_IP][SAFI_MULTICAST]
2100 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2101 || peer->afc[AFI_IP6][SAFI_UNICAST]
2102 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2103 return 1;
2104 return 0;
2105}
2106
2107/* If peer is negotiated at least one address family return 1. */
2108int
2109peer_active_nego (struct peer *peer)
2110{
2111 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2112 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2113 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2114 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2115 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2116 return 1;
2117 return 0;
2118}
2119
2120/* peer_flag_change_type. */
2121enum peer_change_type
2122{
2123 peer_change_none,
2124 peer_change_reset,
2125 peer_change_reset_in,
2126 peer_change_reset_out,
2127};
2128
paul94f2b392005-06-28 12:44:16 +00002129static void
paul718e3742002-12-13 20:15:29 +00002130peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2131 enum peer_change_type type)
2132{
2133 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2134 return;
2135
2136 if (type == peer_change_reset)
2137 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2138 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2139 else if (type == peer_change_reset_in)
2140 {
2141 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2142 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2143 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2144 else
2145 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2146 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2147 }
2148 else if (type == peer_change_reset_out)
2149 bgp_announce_route (peer, afi, safi);
2150}
2151
2152struct peer_flag_action
2153{
2154 /* Peer's flag. */
2155 u_int32_t flag;
2156
2157 /* This flag can be set for peer-group member. */
2158 u_char not_for_member;
2159
2160 /* Action when the flag is changed. */
2161 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002162
2163 /* Peer down cause */
2164 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002165};
2166
2167struct peer_flag_action peer_flag_action_list[] =
2168 {
2169 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2170 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2171 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2172 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2173 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002174 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002175 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002176 { 0, 0, 0 }
2177 };
2178
2179struct peer_flag_action peer_af_flag_action_list[] =
2180 {
2181 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2182 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2183 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2184 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2185 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2186 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2187 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2188 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2189 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2190 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2191 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2192 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2193 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002194 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002195 { 0, 0, 0 }
2196 };
2197
2198/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002199static int
paul718e3742002-12-13 20:15:29 +00002200peer_flag_action_set (struct peer_flag_action *action_list, int size,
2201 struct peer_flag_action *action, u_int32_t flag)
2202{
2203 int i;
2204 int found = 0;
2205 int reset_in = 0;
2206 int reset_out = 0;
2207 struct peer_flag_action *match = NULL;
2208
2209 /* Check peer's frag action. */
2210 for (i = 0; i < size; i++)
2211 {
2212 match = &action_list[i];
2213
2214 if (match->flag == 0)
2215 break;
2216
2217 if (match->flag & flag)
2218 {
2219 found = 1;
2220
2221 if (match->type == peer_change_reset_in)
2222 reset_in = 1;
2223 if (match->type == peer_change_reset_out)
2224 reset_out = 1;
2225 if (match->type == peer_change_reset)
2226 {
2227 reset_in = 1;
2228 reset_out = 1;
2229 }
2230 if (match->not_for_member)
2231 action->not_for_member = 1;
2232 }
2233 }
2234
2235 /* Set peer clear type. */
2236 if (reset_in && reset_out)
2237 action->type = peer_change_reset;
2238 else if (reset_in)
2239 action->type = peer_change_reset_in;
2240 else if (reset_out)
2241 action->type = peer_change_reset_out;
2242 else
2243 action->type = peer_change_none;
2244
2245 return found;
2246}
2247
paul94f2b392005-06-28 12:44:16 +00002248static void
paul718e3742002-12-13 20:15:29 +00002249peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2250{
2251 if (flag == PEER_FLAG_SHUTDOWN)
2252 {
2253 if (CHECK_FLAG (peer->flags, flag))
2254 {
hasso93406d82005-02-02 14:40:33 +00002255 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2256 peer_nsf_stop (peer);
2257
hasso0a486e52005-02-01 20:57:17 +00002258 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2259 if (peer->t_pmax_restart)
2260 {
2261 BGP_TIMER_OFF (peer->t_pmax_restart);
2262 if (BGP_DEBUG (events, EVENTS))
2263 zlog_debug ("%s Maximum-prefix restart timer canceled",
2264 peer->host);
2265 }
2266
hasso93406d82005-02-02 14:40:33 +00002267 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2268 peer_nsf_stop (peer);
2269
paul718e3742002-12-13 20:15:29 +00002270 if (peer->status == Established)
2271 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2272 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2273 else
2274 BGP_EVENT_ADD (peer, BGP_Stop);
2275 }
2276 else
2277 {
2278 peer->v_start = BGP_INIT_START_TIMER;
2279 BGP_EVENT_ADD (peer, BGP_Stop);
2280 }
2281 }
2282 else if (peer->status == Established)
2283 {
hassoc9502432005-02-01 22:01:48 +00002284 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2285 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2286 else if (flag == PEER_FLAG_PASSIVE)
2287 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002288 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002289 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002290
hassoc9502432005-02-01 22:01:48 +00002291 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2292 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002293 }
2294 else
2295 BGP_EVENT_ADD (peer, BGP_Stop);
2296}
2297
2298/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002299static int
paul718e3742002-12-13 20:15:29 +00002300peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2301{
2302 int found;
2303 int size;
2304 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002305 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002306 struct peer_flag_action action;
2307
2308 memset (&action, 0, sizeof (struct peer_flag_action));
2309 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2310
2311 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2312
2313 /* No flag action is found. */
2314 if (! found)
2315 return BGP_ERR_INVALID_FLAG;
2316
2317 /* Not for peer-group member. */
2318 if (action.not_for_member && peer_group_active (peer))
2319 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2320
2321 /* When unset the peer-group member's flag we have to check
2322 peer-group configuration. */
2323 if (! set && peer_group_active (peer))
2324 if (CHECK_FLAG (peer->group->conf->flags, flag))
2325 {
2326 if (flag == PEER_FLAG_SHUTDOWN)
2327 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2328 else
2329 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2330 }
2331
2332 /* Flag conflict check. */
2333 if (set
2334 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2335 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2336 return BGP_ERR_PEER_FLAG_CONFLICT;
2337
2338 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2339 {
2340 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2341 return 0;
2342 if (! set && ! CHECK_FLAG (peer->flags, flag))
2343 return 0;
2344 }
2345
2346 if (set)
2347 SET_FLAG (peer->flags, flag);
2348 else
2349 UNSET_FLAG (peer->flags, flag);
2350
2351 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2352 {
2353 if (action.type == peer_change_reset)
2354 peer_flag_modify_action (peer, flag);
2355
2356 return 0;
2357 }
2358
2359 /* peer-group member updates. */
2360 group = peer->group;
2361
paul1eb8ef22005-04-07 07:30:20 +00002362 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002363 {
2364 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2365 continue;
2366
2367 if (! set && ! CHECK_FLAG (peer->flags, flag))
2368 continue;
2369
2370 if (set)
2371 SET_FLAG (peer->flags, flag);
2372 else
2373 UNSET_FLAG (peer->flags, flag);
2374
2375 if (action.type == peer_change_reset)
2376 peer_flag_modify_action (peer, flag);
2377 }
2378 return 0;
2379}
2380
2381int
2382peer_flag_set (struct peer *peer, u_int32_t flag)
2383{
2384 return peer_flag_modify (peer, flag, 1);
2385}
2386
2387int
2388peer_flag_unset (struct peer *peer, u_int32_t flag)
2389{
2390 return peer_flag_modify (peer, flag, 0);
2391}
2392
paul94f2b392005-06-28 12:44:16 +00002393static int
paul718e3742002-12-13 20:15:29 +00002394peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2395{
2396 if (peer->af_group[afi][safi])
2397 return 1;
2398 return 0;
2399}
2400
paul94f2b392005-06-28 12:44:16 +00002401static int
paul718e3742002-12-13 20:15:29 +00002402peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2403 int set)
2404{
2405 int found;
2406 int size;
paul1eb8ef22005-04-07 07:30:20 +00002407 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002408 struct peer_group *group;
2409 struct peer_flag_action action;
2410
2411 memset (&action, 0, sizeof (struct peer_flag_action));
2412 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2413
2414 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2415
2416 /* No flag action is found. */
2417 if (! found)
2418 return BGP_ERR_INVALID_FLAG;
2419
2420 /* Adress family must be activated. */
2421 if (! peer->afc[afi][safi])
2422 return BGP_ERR_PEER_INACTIVE;
2423
2424 /* Not for peer-group member. */
2425 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2426 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2427
2428 /* Spcecial check for reflector client. */
2429 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2430 && peer_sort (peer) != BGP_PEER_IBGP)
2431 return BGP_ERR_NOT_INTERNAL_PEER;
2432
2433 /* Spcecial check for remove-private-AS. */
2434 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2435 && peer_sort (peer) == BGP_PEER_IBGP)
2436 return BGP_ERR_REMOVE_PRIVATE_AS;
2437
2438 /* When unset the peer-group member's flag we have to check
2439 peer-group configuration. */
2440 if (! set && peer->af_group[afi][safi])
2441 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2442 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2443
2444 /* When current flag configuration is same as requested one. */
2445 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2446 {
2447 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2448 return 0;
2449 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2450 return 0;
2451 }
2452
2453 if (set)
2454 SET_FLAG (peer->af_flags[afi][safi], flag);
2455 else
2456 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2457
2458 /* Execute action when peer is established. */
2459 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2460 && peer->status == Established)
2461 {
2462 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2463 bgp_clear_adj_in (peer, afi, safi);
2464 else
hassoe0701b72004-05-20 09:19:34 +00002465 {
2466 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2467 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2468 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2469 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2470 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2471 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2472 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2473 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2474
2475 peer_change_action (peer, afi, safi, action.type);
2476 }
2477
paul718e3742002-12-13 20:15:29 +00002478 }
2479
2480 /* Peer group member updates. */
2481 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2482 {
2483 group = peer->group;
2484
paul1eb8ef22005-04-07 07:30:20 +00002485 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002486 {
2487 if (! peer->af_group[afi][safi])
2488 continue;
2489
2490 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2491 continue;
2492
2493 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2494 continue;
2495
2496 if (set)
2497 SET_FLAG (peer->af_flags[afi][safi], flag);
2498 else
2499 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2500
2501 if (peer->status == Established)
2502 {
2503 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2504 bgp_clear_adj_in (peer, afi, safi);
2505 else
hassoe0701b72004-05-20 09:19:34 +00002506 {
2507 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2508 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2509 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2510 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2511 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2512 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2513 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2514 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2515
2516 peer_change_action (peer, afi, safi, action.type);
2517 }
paul718e3742002-12-13 20:15:29 +00002518 }
2519 }
2520 }
2521 return 0;
2522}
2523
2524int
2525peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2526{
2527 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2528}
2529
2530int
2531peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2532{
2533 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2534}
2535
2536/* EBGP multihop configuration. */
2537int
2538peer_ebgp_multihop_set (struct peer *peer, int ttl)
2539{
2540 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002541 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002542
2543 if (peer_sort (peer) == BGP_PEER_IBGP)
2544 return 0;
2545
2546 peer->ttl = ttl;
2547
2548 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2549 {
pauleb821182004-05-01 08:44:08 +00002550 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2551 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002552 }
2553 else
2554 {
2555 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002556 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002557 {
2558 if (peer_sort (peer) == BGP_PEER_IBGP)
2559 continue;
paul718e3742002-12-13 20:15:29 +00002560
pauleb821182004-05-01 08:44:08 +00002561 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002562
pauleb821182004-05-01 08:44:08 +00002563 if (peer->fd >= 0)
2564 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2565 }
paul718e3742002-12-13 20:15:29 +00002566 }
2567 return 0;
2568}
2569
2570int
2571peer_ebgp_multihop_unset (struct peer *peer)
2572{
2573 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002574 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002575
2576 if (peer_sort (peer) == BGP_PEER_IBGP)
2577 return 0;
2578
2579 if (peer_group_active (peer))
2580 peer->ttl = peer->group->conf->ttl;
2581 else
2582 peer->ttl = 1;
2583
2584 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2585 {
pauleb821182004-05-01 08:44:08 +00002586 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2587 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002588 }
2589 else
2590 {
2591 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002592 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002593 {
2594 if (peer_sort (peer) == BGP_PEER_IBGP)
2595 continue;
paul718e3742002-12-13 20:15:29 +00002596
pauleb821182004-05-01 08:44:08 +00002597 peer->ttl = 1;
2598
2599 if (peer->fd >= 0)
2600 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2601 }
paul718e3742002-12-13 20:15:29 +00002602 }
2603 return 0;
2604}
2605
2606/* Neighbor description. */
2607int
2608peer_description_set (struct peer *peer, char *desc)
2609{
2610 if (peer->desc)
2611 XFREE (MTYPE_PEER_DESC, peer->desc);
2612
2613 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2614
2615 return 0;
2616}
2617
2618int
2619peer_description_unset (struct peer *peer)
2620{
2621 if (peer->desc)
2622 XFREE (MTYPE_PEER_DESC, peer->desc);
2623
2624 peer->desc = NULL;
2625
2626 return 0;
2627}
2628
2629/* Neighbor update-source. */
2630int
paulfd79ac92004-10-13 05:06:08 +00002631peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002632{
2633 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002634 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002635
2636 if (peer->update_if)
2637 {
2638 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2639 && strcmp (peer->update_if, ifname) == 0)
2640 return 0;
2641
2642 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2643 peer->update_if = NULL;
2644 }
2645
2646 if (peer->update_source)
2647 {
2648 sockunion_free (peer->update_source);
2649 peer->update_source = NULL;
2650 }
2651
2652 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2653
2654 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2655 {
2656 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002657 {
2658 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2659 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2660 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2661 }
paul718e3742002-12-13 20:15:29 +00002662 else
2663 BGP_EVENT_ADD (peer, BGP_Stop);
2664 return 0;
2665 }
2666
2667 /* peer-group member updates. */
2668 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002669 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002670 {
2671 if (peer->update_if)
2672 {
2673 if (strcmp (peer->update_if, ifname) == 0)
2674 continue;
2675
2676 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2677 peer->update_if = NULL;
2678 }
2679
2680 if (peer->update_source)
2681 {
2682 sockunion_free (peer->update_source);
2683 peer->update_source = NULL;
2684 }
2685
2686 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2687
2688 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002689 {
2690 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2691 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2692 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2693 }
paul718e3742002-12-13 20:15:29 +00002694 else
2695 BGP_EVENT_ADD (peer, BGP_Stop);
2696 }
2697 return 0;
2698}
2699
2700int
2701peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2702{
2703 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002704 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002705
2706 if (peer->update_source)
2707 {
2708 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2709 && sockunion_cmp (peer->update_source, su) == 0)
2710 return 0;
2711 sockunion_free (peer->update_source);
2712 peer->update_source = NULL;
2713 }
2714
2715 if (peer->update_if)
2716 {
2717 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2718 peer->update_if = NULL;
2719 }
2720
2721 peer->update_source = sockunion_dup (su);
2722
2723 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2724 {
2725 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002726 {
2727 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2728 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2729 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2730 }
paul718e3742002-12-13 20:15:29 +00002731 else
2732 BGP_EVENT_ADD (peer, BGP_Stop);
2733 return 0;
2734 }
2735
2736 /* peer-group member updates. */
2737 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002738 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002739 {
2740 if (peer->update_source)
2741 {
2742 if (sockunion_cmp (peer->update_source, su) == 0)
2743 continue;
2744 sockunion_free (peer->update_source);
2745 peer->update_source = NULL;
2746 }
2747
2748 if (peer->update_if)
2749 {
2750 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2751 peer->update_if = NULL;
2752 }
2753
2754 peer->update_source = sockunion_dup (su);
2755
2756 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002757 {
2758 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2759 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2760 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2761 }
paul718e3742002-12-13 20:15:29 +00002762 else
2763 BGP_EVENT_ADD (peer, BGP_Stop);
2764 }
2765 return 0;
2766}
2767
2768int
2769peer_update_source_unset (struct peer *peer)
2770{
2771 union sockunion *su;
2772 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002773 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002774
2775 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2776 && ! peer->update_source
2777 && ! peer->update_if)
2778 return 0;
2779
2780 if (peer->update_source)
2781 {
2782 sockunion_free (peer->update_source);
2783 peer->update_source = NULL;
2784 }
2785 if (peer->update_if)
2786 {
2787 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2788 peer->update_if = NULL;
2789 }
2790
2791 if (peer_group_active (peer))
2792 {
2793 group = peer->group;
2794
2795 if (group->conf->update_source)
2796 {
2797 su = sockunion_dup (group->conf->update_source);
2798 peer->update_source = su;
2799 }
2800 else if (group->conf->update_if)
2801 peer->update_if =
2802 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2803 }
2804
2805 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2806 {
2807 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002808 {
2809 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2810 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2811 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2812 }
paul718e3742002-12-13 20:15:29 +00002813 else
2814 BGP_EVENT_ADD (peer, BGP_Stop);
2815 return 0;
2816 }
2817
2818 /* peer-group member updates. */
2819 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002820 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002821 {
2822 if (! peer->update_source && ! peer->update_if)
2823 continue;
2824
2825 if (peer->update_source)
2826 {
2827 sockunion_free (peer->update_source);
2828 peer->update_source = NULL;
2829 }
2830
2831 if (peer->update_if)
2832 {
2833 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2834 peer->update_if = NULL;
2835 }
2836
2837 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002838 {
2839 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2840 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2841 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2842 }
paul718e3742002-12-13 20:15:29 +00002843 else
2844 BGP_EVENT_ADD (peer, BGP_Stop);
2845 }
2846 return 0;
2847}
2848
2849int
2850peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002851 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002852{
2853 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002854 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002855
2856 /* Adress family must be activated. */
2857 if (! peer->afc[afi][safi])
2858 return BGP_ERR_PEER_INACTIVE;
2859
2860 /* Default originate can't be used for peer group memeber. */
2861 if (peer_is_group_member (peer, afi, safi))
2862 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2863
2864 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2865 || (rmap && ! peer->default_rmap[afi][safi].name)
2866 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2867 {
2868 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2869
2870 if (rmap)
2871 {
2872 if (peer->default_rmap[afi][safi].name)
2873 free (peer->default_rmap[afi][safi].name);
2874 peer->default_rmap[afi][safi].name = strdup (rmap);
2875 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2876 }
2877 }
2878
2879 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2880 {
2881 if (peer->status == Established && peer->afc_nego[afi][safi])
2882 bgp_default_originate (peer, afi, safi, 0);
2883 return 0;
2884 }
2885
2886 /* peer-group member updates. */
2887 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002888 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002889 {
2890 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2891
2892 if (rmap)
2893 {
2894 if (peer->default_rmap[afi][safi].name)
2895 free (peer->default_rmap[afi][safi].name);
2896 peer->default_rmap[afi][safi].name = strdup (rmap);
2897 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2898 }
2899
2900 if (peer->status == Established && peer->afc_nego[afi][safi])
2901 bgp_default_originate (peer, afi, safi, 0);
2902 }
2903 return 0;
2904}
2905
2906int
2907peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2908{
2909 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002910 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002911
2912 /* Adress family must be activated. */
2913 if (! peer->afc[afi][safi])
2914 return BGP_ERR_PEER_INACTIVE;
2915
2916 /* Default originate can't be used for peer group memeber. */
2917 if (peer_is_group_member (peer, afi, safi))
2918 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2919
2920 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2921 {
2922 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2923
2924 if (peer->default_rmap[afi][safi].name)
2925 free (peer->default_rmap[afi][safi].name);
2926 peer->default_rmap[afi][safi].name = NULL;
2927 peer->default_rmap[afi][safi].map = NULL;
2928 }
2929
2930 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2931 {
2932 if (peer->status == Established && peer->afc_nego[afi][safi])
2933 bgp_default_originate (peer, afi, safi, 1);
2934 return 0;
2935 }
2936
2937 /* peer-group member updates. */
2938 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002939 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002940 {
2941 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2942
2943 if (peer->default_rmap[afi][safi].name)
2944 free (peer->default_rmap[afi][safi].name);
2945 peer->default_rmap[afi][safi].name = NULL;
2946 peer->default_rmap[afi][safi].map = NULL;
2947
2948 if (peer->status == Established && peer->afc_nego[afi][safi])
2949 bgp_default_originate (peer, afi, safi, 1);
2950 }
2951 return 0;
2952}
2953
2954int
2955peer_port_set (struct peer *peer, u_int16_t port)
2956{
2957 peer->port = port;
2958 return 0;
2959}
2960
2961int
2962peer_port_unset (struct peer *peer)
2963{
2964 peer->port = BGP_PORT_DEFAULT;
2965 return 0;
2966}
2967
2968/* neighbor weight. */
2969int
2970peer_weight_set (struct peer *peer, u_int16_t weight)
2971{
2972 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002973 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002974
2975 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2976 peer->weight = weight;
2977
2978 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2979 return 0;
2980
2981 /* peer-group member updates. */
2982 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002983 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002984 {
2985 peer->weight = group->conf->weight;
2986 }
2987 return 0;
2988}
2989
2990int
2991peer_weight_unset (struct peer *peer)
2992{
2993 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002994 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002995
2996 /* Set default weight. */
2997 if (peer_group_active (peer))
2998 peer->weight = peer->group->conf->weight;
2999 else
3000 peer->weight = 0;
3001
3002 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3003
3004 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3005 return 0;
3006
3007 /* peer-group member updates. */
3008 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003009 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003010 {
3011 peer->weight = 0;
3012 }
3013 return 0;
3014}
3015
3016int
3017peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3018{
3019 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003020 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003021
3022 /* Not for peer group memeber. */
3023 if (peer_group_active (peer))
3024 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3025
3026 /* keepalive value check. */
3027 if (keepalive > 65535)
3028 return BGP_ERR_INVALID_VALUE;
3029
3030 /* Holdtime value check. */
3031 if (holdtime > 65535)
3032 return BGP_ERR_INVALID_VALUE;
3033
3034 /* Holdtime value must be either 0 or greater than 3. */
3035 if (holdtime < 3 && holdtime != 0)
3036 return BGP_ERR_INVALID_VALUE;
3037
3038 /* Set value to the configuration. */
3039 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3040 peer->holdtime = holdtime;
3041 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3042
3043 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3044 return 0;
3045
3046 /* peer-group member updates. */
3047 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003048 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003049 {
3050 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3051 peer->holdtime = group->conf->holdtime;
3052 peer->keepalive = group->conf->keepalive;
3053 }
3054 return 0;
3055}
3056
3057int
3058peer_timers_unset (struct peer *peer)
3059{
3060 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003061 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003062
3063 if (peer_group_active (peer))
3064 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3065
3066 /* Clear configuration. */
3067 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3068 peer->keepalive = 0;
3069 peer->holdtime = 0;
3070
3071 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3072 return 0;
3073
3074 /* peer-group member updates. */
3075 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003076 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003077 {
3078 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3079 peer->holdtime = 0;
3080 peer->keepalive = 0;
3081 }
3082
3083 return 0;
3084}
3085
3086int
3087peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3088{
3089 if (peer_group_active (peer))
3090 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3091
3092 if (connect > 65535)
3093 return BGP_ERR_INVALID_VALUE;
3094
3095 /* Set value to the configuration. */
3096 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3097 peer->connect = connect;
3098
3099 /* Set value to timer setting. */
3100 peer->v_connect = connect;
3101
3102 return 0;
3103}
3104
3105int
3106peer_timers_connect_unset (struct peer *peer)
3107{
3108 if (peer_group_active (peer))
3109 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3110
3111 /* Clear configuration. */
3112 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3113 peer->connect = 0;
3114
3115 /* Set timer setting to default value. */
3116 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3117
3118 return 0;
3119}
3120
3121int
3122peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3123{
3124 if (peer_group_active (peer))
3125 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3126
3127 if (routeadv > 600)
3128 return BGP_ERR_INVALID_VALUE;
3129
3130 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3131 peer->routeadv = routeadv;
3132 peer->v_routeadv = routeadv;
3133
3134 return 0;
3135}
3136
3137int
3138peer_advertise_interval_unset (struct peer *peer)
3139{
3140 if (peer_group_active (peer))
3141 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3142
3143 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3144 peer->routeadv = 0;
3145
3146 if (peer_sort (peer) == BGP_PEER_IBGP)
3147 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3148 else
3149 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3150
3151 return 0;
3152}
3153
paul718e3742002-12-13 20:15:29 +00003154/* neighbor interface */
3155int
paulfd79ac92004-10-13 05:06:08 +00003156peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003157{
3158 if (peer->ifname)
3159 free (peer->ifname);
3160 peer->ifname = strdup (str);
3161
3162 return 0;
3163}
3164
3165int
3166peer_interface_unset (struct peer *peer)
3167{
3168 if (peer->ifname)
3169 free (peer->ifname);
3170 peer->ifname = NULL;
3171
3172 return 0;
3173}
3174
3175/* Allow-as in. */
3176int
3177peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3178{
3179 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003180 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003181
3182 if (allow_num < 1 || allow_num > 10)
3183 return BGP_ERR_INVALID_VALUE;
3184
3185 if (peer->allowas_in[afi][safi] != allow_num)
3186 {
3187 peer->allowas_in[afi][safi] = allow_num;
3188 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3189 peer_change_action (peer, afi, safi, peer_change_reset_in);
3190 }
3191
3192 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3193 return 0;
3194
3195 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003196 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003197 {
3198 if (peer->allowas_in[afi][safi] != allow_num)
3199 {
3200 peer->allowas_in[afi][safi] = allow_num;
3201 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3202 peer_change_action (peer, afi, safi, peer_change_reset_in);
3203 }
3204
3205 }
3206 return 0;
3207}
3208
3209int
3210peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3211{
3212 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003213 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003214
3215 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3216 {
3217 peer->allowas_in[afi][safi] = 0;
3218 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3219 }
3220
3221 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3222 return 0;
3223
3224 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003225 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003226 {
3227 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3228 {
3229 peer->allowas_in[afi][safi] = 0;
3230 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3231 }
3232 }
3233 return 0;
3234}
3235
3236int
3237peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3238{
3239 struct bgp *bgp = peer->bgp;
3240 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003241 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003242
3243 if (peer_sort (peer) != BGP_PEER_EBGP
3244 && peer_sort (peer) != BGP_PEER_INTERNAL)
3245 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3246
3247 if (bgp->as == as)
3248 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3249
3250 if (peer_group_active (peer))
3251 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3252
3253 if (peer->change_local_as == as &&
3254 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3255 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3256 return 0;
3257
3258 peer->change_local_as = as;
3259 if (no_prepend)
3260 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3261 else
3262 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3263
3264 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3265 {
3266 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003267 {
3268 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3269 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3270 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3271 }
paul718e3742002-12-13 20:15:29 +00003272 else
3273 BGP_EVENT_ADD (peer, BGP_Stop);
3274
3275 return 0;
3276 }
3277
3278 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003279 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003280 {
3281 peer->change_local_as = as;
3282 if (no_prepend)
3283 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3284 else
3285 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3286
3287 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003288 {
3289 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3290 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3291 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3292 }
paul718e3742002-12-13 20:15:29 +00003293 else
3294 BGP_EVENT_ADD (peer, BGP_Stop);
3295 }
3296
3297 return 0;
3298}
3299
3300int
3301peer_local_as_unset (struct peer *peer)
3302{
3303 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003304 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003305
3306 if (peer_group_active (peer))
3307 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3308
3309 if (! peer->change_local_as)
3310 return 0;
3311
3312 peer->change_local_as = 0;
3313 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3314
3315 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3316 {
3317 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003318 {
3319 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3320 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3321 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3322 }
paul718e3742002-12-13 20:15:29 +00003323 else
3324 BGP_EVENT_ADD (peer, BGP_Stop);
3325
3326 return 0;
3327 }
3328
3329 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003330 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003331 {
3332 peer->change_local_as = 0;
3333 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3334
3335 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003336 {
3337 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3338 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3339 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3340 }
paul718e3742002-12-13 20:15:29 +00003341 else
3342 BGP_EVENT_ADD (peer, BGP_Stop);
3343 }
3344 return 0;
3345}
3346
3347/* Set distribute list to the peer. */
3348int
3349peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003350 const char *name)
paul718e3742002-12-13 20:15:29 +00003351{
3352 struct bgp_filter *filter;
3353 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003354 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003355
3356 if (! peer->afc[afi][safi])
3357 return BGP_ERR_PEER_INACTIVE;
3358
3359 if (direct != FILTER_IN && direct != FILTER_OUT)
3360 return BGP_ERR_INVALID_VALUE;
3361
3362 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3363 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3364
3365 filter = &peer->filter[afi][safi];
3366
3367 if (filter->plist[direct].name)
3368 return BGP_ERR_PEER_FILTER_CONFLICT;
3369
3370 if (filter->dlist[direct].name)
3371 free (filter->dlist[direct].name);
3372 filter->dlist[direct].name = strdup (name);
3373 filter->dlist[direct].alist = access_list_lookup (afi, name);
3374
3375 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3376 return 0;
3377
3378 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003379 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003380 {
3381 filter = &peer->filter[afi][safi];
3382
3383 if (! peer->af_group[afi][safi])
3384 continue;
3385
3386 if (filter->dlist[direct].name)
3387 free (filter->dlist[direct].name);
3388 filter->dlist[direct].name = strdup (name);
3389 filter->dlist[direct].alist = access_list_lookup (afi, name);
3390 }
3391
3392 return 0;
3393}
3394
3395int
3396peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3397{
3398 struct bgp_filter *filter;
3399 struct bgp_filter *gfilter;
3400 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003401 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003402
3403 if (! peer->afc[afi][safi])
3404 return BGP_ERR_PEER_INACTIVE;
3405
3406 if (direct != FILTER_IN && direct != FILTER_OUT)
3407 return BGP_ERR_INVALID_VALUE;
3408
3409 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3410 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3411
3412 filter = &peer->filter[afi][safi];
3413
3414 /* apply peer-group filter */
3415 if (peer->af_group[afi][safi])
3416 {
3417 gfilter = &peer->group->conf->filter[afi][safi];
3418
3419 if (gfilter->dlist[direct].name)
3420 {
3421 if (filter->dlist[direct].name)
3422 free (filter->dlist[direct].name);
3423 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3424 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3425 return 0;
3426 }
3427 }
3428
3429 if (filter->dlist[direct].name)
3430 free (filter->dlist[direct].name);
3431 filter->dlist[direct].name = NULL;
3432 filter->dlist[direct].alist = NULL;
3433
3434 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3435 return 0;
3436
3437 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003438 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003439 {
3440 filter = &peer->filter[afi][safi];
3441
3442 if (! peer->af_group[afi][safi])
3443 continue;
3444
3445 if (filter->dlist[direct].name)
3446 free (filter->dlist[direct].name);
3447 filter->dlist[direct].name = NULL;
3448 filter->dlist[direct].alist = NULL;
3449 }
3450
3451 return 0;
3452}
3453
3454/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003455static void
paul718e3742002-12-13 20:15:29 +00003456peer_distribute_update (struct access_list *access)
3457{
3458 afi_t afi;
3459 safi_t safi;
3460 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003461 struct listnode *mnode, *mnnode;
3462 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003463 struct bgp *bgp;
3464 struct peer *peer;
3465 struct peer_group *group;
3466 struct bgp_filter *filter;
3467
paul1eb8ef22005-04-07 07:30:20 +00003468 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003469 {
paul1eb8ef22005-04-07 07:30:20 +00003470 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003471 {
3472 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3473 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3474 {
3475 filter = &peer->filter[afi][safi];
3476
3477 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3478 {
3479 if (filter->dlist[direct].name)
3480 filter->dlist[direct].alist =
3481 access_list_lookup (afi, filter->dlist[direct].name);
3482 else
3483 filter->dlist[direct].alist = NULL;
3484 }
3485 }
3486 }
paul1eb8ef22005-04-07 07:30:20 +00003487 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003488 {
3489 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3490 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3491 {
3492 filter = &group->conf->filter[afi][safi];
3493
3494 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3495 {
3496 if (filter->dlist[direct].name)
3497 filter->dlist[direct].alist =
3498 access_list_lookup (afi, filter->dlist[direct].name);
3499 else
3500 filter->dlist[direct].alist = NULL;
3501 }
3502 }
3503 }
3504 }
3505}
3506
3507/* Set prefix list to the peer. */
3508int
3509peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003510 const char *name)
paul718e3742002-12-13 20:15:29 +00003511{
3512 struct bgp_filter *filter;
3513 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003514 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003515
3516 if (! peer->afc[afi][safi])
3517 return BGP_ERR_PEER_INACTIVE;
3518
3519 if (direct != FILTER_IN && direct != FILTER_OUT)
3520 return BGP_ERR_INVALID_VALUE;
3521
3522 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3523 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3524
3525 filter = &peer->filter[afi][safi];
3526
3527 if (filter->dlist[direct].name)
3528 return BGP_ERR_PEER_FILTER_CONFLICT;
3529
3530 if (filter->plist[direct].name)
3531 free (filter->plist[direct].name);
3532 filter->plist[direct].name = strdup (name);
3533 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3534
3535 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3536 return 0;
3537
3538 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003539 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003540 {
3541 filter = &peer->filter[afi][safi];
3542
3543 if (! peer->af_group[afi][safi])
3544 continue;
3545
3546 if (filter->plist[direct].name)
3547 free (filter->plist[direct].name);
3548 filter->plist[direct].name = strdup (name);
3549 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3550 }
3551 return 0;
3552}
3553
3554int
3555peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3556{
3557 struct bgp_filter *filter;
3558 struct bgp_filter *gfilter;
3559 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003560 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003561
3562 if (! peer->afc[afi][safi])
3563 return BGP_ERR_PEER_INACTIVE;
3564
3565 if (direct != FILTER_IN && direct != FILTER_OUT)
3566 return BGP_ERR_INVALID_VALUE;
3567
3568 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3569 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3570
3571 filter = &peer->filter[afi][safi];
3572
3573 /* apply peer-group filter */
3574 if (peer->af_group[afi][safi])
3575 {
3576 gfilter = &peer->group->conf->filter[afi][safi];
3577
3578 if (gfilter->plist[direct].name)
3579 {
3580 if (filter->plist[direct].name)
3581 free (filter->plist[direct].name);
3582 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3583 filter->plist[direct].plist = gfilter->plist[direct].plist;
3584 return 0;
3585 }
3586 }
3587
3588 if (filter->plist[direct].name)
3589 free (filter->plist[direct].name);
3590 filter->plist[direct].name = NULL;
3591 filter->plist[direct].plist = NULL;
3592
3593 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3594 return 0;
3595
3596 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003597 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003598 {
3599 filter = &peer->filter[afi][safi];
3600
3601 if (! peer->af_group[afi][safi])
3602 continue;
3603
3604 if (filter->plist[direct].name)
3605 free (filter->plist[direct].name);
3606 filter->plist[direct].name = NULL;
3607 filter->plist[direct].plist = NULL;
3608 }
3609
3610 return 0;
3611}
3612
3613/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003614static void
paul718e3742002-12-13 20:15:29 +00003615peer_prefix_list_update (struct prefix_list *plist)
3616{
paul1eb8ef22005-04-07 07:30:20 +00003617 struct listnode *mnode, *mnnode;
3618 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003619 struct bgp *bgp;
3620 struct peer *peer;
3621 struct peer_group *group;
3622 struct bgp_filter *filter;
3623 afi_t afi;
3624 safi_t safi;
3625 int direct;
3626
paul1eb8ef22005-04-07 07:30:20 +00003627 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003628 {
paul1eb8ef22005-04-07 07:30:20 +00003629 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003630 {
3631 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3632 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3633 {
3634 filter = &peer->filter[afi][safi];
3635
3636 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3637 {
3638 if (filter->plist[direct].name)
3639 filter->plist[direct].plist =
3640 prefix_list_lookup (afi, filter->plist[direct].name);
3641 else
3642 filter->plist[direct].plist = NULL;
3643 }
3644 }
3645 }
paul1eb8ef22005-04-07 07:30:20 +00003646 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003647 {
3648 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3649 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3650 {
3651 filter = &group->conf->filter[afi][safi];
3652
3653 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3654 {
3655 if (filter->plist[direct].name)
3656 filter->plist[direct].plist =
3657 prefix_list_lookup (afi, filter->plist[direct].name);
3658 else
3659 filter->plist[direct].plist = NULL;
3660 }
3661 }
3662 }
3663 }
3664}
3665
3666int
3667peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003668 const char *name)
paul718e3742002-12-13 20:15:29 +00003669{
3670 struct bgp_filter *filter;
3671 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003672 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003673
3674 if (! peer->afc[afi][safi])
3675 return BGP_ERR_PEER_INACTIVE;
3676
3677 if (direct != FILTER_IN && direct != FILTER_OUT)
3678 return BGP_ERR_INVALID_VALUE;
3679
3680 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3681 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3682
3683 filter = &peer->filter[afi][safi];
3684
3685 if (filter->aslist[direct].name)
3686 free (filter->aslist[direct].name);
3687 filter->aslist[direct].name = strdup (name);
3688 filter->aslist[direct].aslist = as_list_lookup (name);
3689
3690 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3691 return 0;
3692
3693 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003694 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003695 {
3696 filter = &peer->filter[afi][safi];
3697
3698 if (! peer->af_group[afi][safi])
3699 continue;
3700
3701 if (filter->aslist[direct].name)
3702 free (filter->aslist[direct].name);
3703 filter->aslist[direct].name = strdup (name);
3704 filter->aslist[direct].aslist = as_list_lookup (name);
3705 }
3706 return 0;
3707}
3708
3709int
3710peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3711{
3712 struct bgp_filter *filter;
3713 struct bgp_filter *gfilter;
3714 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003715 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003716
3717 if (! peer->afc[afi][safi])
3718 return BGP_ERR_PEER_INACTIVE;
3719
hassob5f29602005-05-25 21:00:28 +00003720 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003721 return BGP_ERR_INVALID_VALUE;
3722
hassob5f29602005-05-25 21:00:28 +00003723 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003724 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3725
3726 filter = &peer->filter[afi][safi];
3727
3728 /* apply peer-group filter */
3729 if (peer->af_group[afi][safi])
3730 {
3731 gfilter = &peer->group->conf->filter[afi][safi];
3732
3733 if (gfilter->aslist[direct].name)
3734 {
3735 if (filter->aslist[direct].name)
3736 free (filter->aslist[direct].name);
3737 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3738 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3739 return 0;
3740 }
3741 }
3742
3743 if (filter->aslist[direct].name)
3744 free (filter->aslist[direct].name);
3745 filter->aslist[direct].name = NULL;
3746 filter->aslist[direct].aslist = NULL;
3747
3748 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3749 return 0;
3750
3751 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003752 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003753 {
3754 filter = &peer->filter[afi][safi];
3755
3756 if (! peer->af_group[afi][safi])
3757 continue;
3758
3759 if (filter->aslist[direct].name)
3760 free (filter->aslist[direct].name);
3761 filter->aslist[direct].name = NULL;
3762 filter->aslist[direct].aslist = NULL;
3763 }
3764
3765 return 0;
3766}
3767
paul94f2b392005-06-28 12:44:16 +00003768static void
paul718e3742002-12-13 20:15:29 +00003769peer_aslist_update ()
3770{
3771 afi_t afi;
3772 safi_t safi;
3773 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003774 struct listnode *mnode, *mnnode;
3775 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003776 struct bgp *bgp;
3777 struct peer *peer;
3778 struct peer_group *group;
3779 struct bgp_filter *filter;
3780
paul1eb8ef22005-04-07 07:30:20 +00003781 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003782 {
paul1eb8ef22005-04-07 07:30:20 +00003783 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003784 {
3785 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3786 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3787 {
3788 filter = &peer->filter[afi][safi];
3789
3790 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3791 {
3792 if (filter->aslist[direct].name)
3793 filter->aslist[direct].aslist =
3794 as_list_lookup (filter->aslist[direct].name);
3795 else
3796 filter->aslist[direct].aslist = NULL;
3797 }
3798 }
3799 }
paul1eb8ef22005-04-07 07:30:20 +00003800 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003801 {
3802 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3803 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3804 {
3805 filter = &group->conf->filter[afi][safi];
3806
3807 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3808 {
3809 if (filter->aslist[direct].name)
3810 filter->aslist[direct].aslist =
3811 as_list_lookup (filter->aslist[direct].name);
3812 else
3813 filter->aslist[direct].aslist = NULL;
3814 }
3815 }
3816 }
3817 }
3818}
3819
3820/* Set route-map to the peer. */
3821int
3822peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003823 const char *name)
paul718e3742002-12-13 20:15:29 +00003824{
3825 struct bgp_filter *filter;
3826 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003827 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003828
3829 if (! peer->afc[afi][safi])
3830 return BGP_ERR_PEER_INACTIVE;
3831
paulfee0f4c2004-09-13 05:12:46 +00003832 if (direct != RMAP_IN && direct != RMAP_OUT &&
3833 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003834 return BGP_ERR_INVALID_VALUE;
3835
paulfee0f4c2004-09-13 05:12:46 +00003836 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3837 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003838 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3839
3840 filter = &peer->filter[afi][safi];
3841
3842 if (filter->map[direct].name)
3843 free (filter->map[direct].name);
3844
3845 filter->map[direct].name = strdup (name);
3846 filter->map[direct].map = route_map_lookup_by_name (name);
3847
3848 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3849 return 0;
3850
3851 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003852 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003853 {
3854 filter = &peer->filter[afi][safi];
3855
3856 if (! peer->af_group[afi][safi])
3857 continue;
3858
3859 if (filter->map[direct].name)
3860 free (filter->map[direct].name);
3861 filter->map[direct].name = strdup (name);
3862 filter->map[direct].map = route_map_lookup_by_name (name);
3863 }
3864 return 0;
3865}
3866
3867/* Unset route-map from the peer. */
3868int
3869peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3870{
3871 struct bgp_filter *filter;
3872 struct bgp_filter *gfilter;
3873 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003874 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003875
3876 if (! peer->afc[afi][safi])
3877 return BGP_ERR_PEER_INACTIVE;
3878
hassob5f29602005-05-25 21:00:28 +00003879 if (direct != RMAP_IN && direct != RMAP_OUT &&
3880 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003881 return BGP_ERR_INVALID_VALUE;
3882
hassob5f29602005-05-25 21:00:28 +00003883 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3884 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003885 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3886
3887 filter = &peer->filter[afi][safi];
3888
3889 /* apply peer-group filter */
3890 if (peer->af_group[afi][safi])
3891 {
3892 gfilter = &peer->group->conf->filter[afi][safi];
3893
3894 if (gfilter->map[direct].name)
3895 {
3896 if (filter->map[direct].name)
3897 free (filter->map[direct].name);
3898 filter->map[direct].name = strdup (gfilter->map[direct].name);
3899 filter->map[direct].map = gfilter->map[direct].map;
3900 return 0;
3901 }
3902 }
3903
3904 if (filter->map[direct].name)
3905 free (filter->map[direct].name);
3906 filter->map[direct].name = NULL;
3907 filter->map[direct].map = NULL;
3908
3909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3910 return 0;
3911
3912 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003913 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003914 {
3915 filter = &peer->filter[afi][safi];
3916
3917 if (! peer->af_group[afi][safi])
3918 continue;
3919
3920 if (filter->map[direct].name)
3921 free (filter->map[direct].name);
3922 filter->map[direct].name = NULL;
3923 filter->map[direct].map = NULL;
3924 }
3925 return 0;
3926}
3927
3928/* Set unsuppress-map to the peer. */
3929int
paulfd79ac92004-10-13 05:06:08 +00003930peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3931 const char *name)
paul718e3742002-12-13 20:15:29 +00003932{
3933 struct bgp_filter *filter;
3934 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003935 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003936
3937 if (! peer->afc[afi][safi])
3938 return BGP_ERR_PEER_INACTIVE;
3939
3940 if (peer_is_group_member (peer, afi, safi))
3941 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3942
3943 filter = &peer->filter[afi][safi];
3944
3945 if (filter->usmap.name)
3946 free (filter->usmap.name);
3947
3948 filter->usmap.name = strdup (name);
3949 filter->usmap.map = route_map_lookup_by_name (name);
3950
3951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3952 return 0;
3953
3954 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003955 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003956 {
3957 filter = &peer->filter[afi][safi];
3958
3959 if (! peer->af_group[afi][safi])
3960 continue;
3961
3962 if (filter->usmap.name)
3963 free (filter->usmap.name);
3964 filter->usmap.name = strdup (name);
3965 filter->usmap.map = route_map_lookup_by_name (name);
3966 }
3967 return 0;
3968}
3969
3970/* Unset route-map from the peer. */
3971int
3972peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3973{
3974 struct bgp_filter *filter;
3975 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003976 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003977
3978 if (! peer->afc[afi][safi])
3979 return BGP_ERR_PEER_INACTIVE;
3980
3981 if (peer_is_group_member (peer, afi, safi))
3982 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3983
3984 filter = &peer->filter[afi][safi];
3985
3986 if (filter->usmap.name)
3987 free (filter->usmap.name);
3988 filter->usmap.name = NULL;
3989 filter->usmap.map = NULL;
3990
3991 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3992 return 0;
3993
3994 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003995 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003996 {
3997 filter = &peer->filter[afi][safi];
3998
3999 if (! peer->af_group[afi][safi])
4000 continue;
4001
4002 if (filter->usmap.name)
4003 free (filter->usmap.name);
4004 filter->usmap.name = NULL;
4005 filter->usmap.map = NULL;
4006 }
4007 return 0;
4008}
4009
4010int
4011peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004012 u_int32_t max, u_char threshold,
4013 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004014{
4015 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004016 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004017
4018 if (! peer->afc[afi][safi])
4019 return BGP_ERR_PEER_INACTIVE;
4020
4021 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4022 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004023 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004024 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004025 if (warning)
4026 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4027 else
4028 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4029
4030 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4031 return 0;
4032
4033 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004034 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004035 {
4036 if (! peer->af_group[afi][safi])
4037 continue;
4038
4039 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4040 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004041 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004042 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004043 if (warning)
4044 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4045 else
4046 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4047 }
4048 return 0;
4049}
4050
4051int
4052peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4053{
4054 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004055 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004056
4057 if (! peer->afc[afi][safi])
4058 return BGP_ERR_PEER_INACTIVE;
4059
4060 /* apply peer-group config */
4061 if (peer->af_group[afi][safi])
4062 {
4063 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4064 PEER_FLAG_MAX_PREFIX))
4065 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4066 else
4067 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4068
4069 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4070 PEER_FLAG_MAX_PREFIX_WARNING))
4071 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4072 else
4073 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4074
4075 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004076 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004077 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004078 return 0;
4079 }
4080
4081 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4082 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4083 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004084 peer->pmax_threshold[afi][safi] = 0;
4085 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004086
4087 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4088 return 0;
4089
4090 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004091 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004092 {
4093 if (! peer->af_group[afi][safi])
4094 continue;
4095
4096 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4097 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4098 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004099 peer->pmax_threshold[afi][safi] = 0;
4100 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004101 }
4102 return 0;
4103}
4104
4105int
4106peer_clear (struct peer *peer)
4107{
4108 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4109 {
hasso0a486e52005-02-01 20:57:17 +00004110 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4111 {
4112 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4113 if (peer->t_pmax_restart)
4114 {
4115 BGP_TIMER_OFF (peer->t_pmax_restart);
4116 if (BGP_DEBUG (events, EVENTS))
4117 zlog_debug ("%s Maximum-prefix restart timer canceled",
4118 peer->host);
4119 }
4120 BGP_EVENT_ADD (peer, BGP_Start);
4121 return 0;
4122 }
4123
paul718e3742002-12-13 20:15:29 +00004124 peer->v_start = BGP_INIT_START_TIMER;
4125 if (peer->status == Established)
4126 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4127 BGP_NOTIFY_CEASE_ADMIN_RESET);
4128 else
4129 BGP_EVENT_ADD (peer, BGP_Stop);
4130 }
4131 return 0;
4132}
4133
4134int
4135peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4136 enum bgp_clear_type stype)
4137{
4138 if (peer->status != Established)
4139 return 0;
4140
4141 if (! peer->afc[afi][safi])
4142 return BGP_ERR_AF_UNCONFIGURED;
4143
paulfee0f4c2004-09-13 05:12:46 +00004144 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4145 {
4146 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4147 return 0;
4148 bgp_check_local_routes_rsclient (peer, afi, safi);
4149 bgp_soft_reconfig_rsclient (peer, afi, safi);
4150 }
4151
paul718e3742002-12-13 20:15:29 +00004152 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4153 bgp_announce_route (peer, afi, safi);
4154
4155 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4156 {
4157 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4158 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4159 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4160 {
4161 struct bgp_filter *filter = &peer->filter[afi][safi];
4162 u_char prefix_type;
4163
4164 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4165 prefix_type = ORF_TYPE_PREFIX;
4166 else
4167 prefix_type = ORF_TYPE_PREFIX_OLD;
4168
4169 if (filter->plist[FILTER_IN].plist)
4170 {
4171 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4172 bgp_route_refresh_send (peer, afi, safi,
4173 prefix_type, REFRESH_DEFER, 1);
4174 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4175 REFRESH_IMMEDIATE, 0);
4176 }
4177 else
4178 {
4179 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4180 bgp_route_refresh_send (peer, afi, safi,
4181 prefix_type, REFRESH_IMMEDIATE, 1);
4182 else
4183 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4184 }
4185 return 0;
4186 }
4187 }
4188
4189 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4190 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4191 {
4192 /* If neighbor has soft reconfiguration inbound flag.
4193 Use Adj-RIB-In database. */
4194 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4195 bgp_soft_reconfig_in (peer, afi, safi);
4196 else
4197 {
4198 /* If neighbor has route refresh capability, send route refresh
4199 message to the peer. */
4200 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4201 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4202 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4203 else
4204 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4205 }
4206 }
4207 return 0;
4208}
4209
paulfd79ac92004-10-13 05:06:08 +00004210/* Display peer uptime.*/
4211/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004212char *
4213peer_uptime (time_t uptime2, char *buf, size_t len)
4214{
4215 time_t uptime1;
4216 struct tm *tm;
4217
4218 /* Check buffer length. */
4219 if (len < BGP_UPTIME_LEN)
4220 {
gdtc29fdba2004-12-09 14:46:46 +00004221 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004222 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004223 /* XXX: should return status instead of buf... */
4224 snprintf (buf, len, "<error> ");
4225 return buf;
paul718e3742002-12-13 20:15:29 +00004226 }
4227
4228 /* If there is no connection has been done before print `never'. */
4229 if (uptime2 == 0)
4230 {
4231 snprintf (buf, len, "never ");
4232 return buf;
4233 }
4234
4235 /* Get current time. */
4236 uptime1 = time (NULL);
4237 uptime1 -= uptime2;
4238 tm = gmtime (&uptime1);
4239
4240 /* Making formatted timer strings. */
4241#define ONE_DAY_SECOND 60*60*24
4242#define ONE_WEEK_SECOND 60*60*24*7
4243
4244 if (uptime1 < ONE_DAY_SECOND)
4245 snprintf (buf, len, "%02d:%02d:%02d",
4246 tm->tm_hour, tm->tm_min, tm->tm_sec);
4247 else if (uptime1 < ONE_WEEK_SECOND)
4248 snprintf (buf, len, "%dd%02dh%02dm",
4249 tm->tm_yday, tm->tm_hour, tm->tm_min);
4250 else
4251 snprintf (buf, len, "%02dw%dd%02dh",
4252 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4253 return buf;
4254}
4255
paul94f2b392005-06-28 12:44:16 +00004256static void
paul718e3742002-12-13 20:15:29 +00004257bgp_config_write_filter (struct vty *vty, struct peer *peer,
4258 afi_t afi, safi_t safi)
4259{
4260 struct bgp_filter *filter;
4261 struct bgp_filter *gfilter = NULL;
4262 char *addr;
4263 int in = FILTER_IN;
4264 int out = FILTER_OUT;
4265
4266 addr = peer->host;
4267 filter = &peer->filter[afi][safi];
4268 if (peer->af_group[afi][safi])
4269 gfilter = &peer->group->conf->filter[afi][safi];
4270
4271 /* distribute-list. */
4272 if (filter->dlist[in].name)
4273 if (! gfilter || ! gfilter->dlist[in].name
4274 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4275 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4276 filter->dlist[in].name, VTY_NEWLINE);
4277 if (filter->dlist[out].name && ! gfilter)
4278 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4279 filter->dlist[out].name, VTY_NEWLINE);
4280
4281 /* prefix-list. */
4282 if (filter->plist[in].name)
4283 if (! gfilter || ! gfilter->plist[in].name
4284 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4285 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4286 filter->plist[in].name, VTY_NEWLINE);
4287 if (filter->plist[out].name && ! gfilter)
4288 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4289 filter->plist[out].name, VTY_NEWLINE);
4290
4291 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004292 if (filter->map[RMAP_IN].name)
4293 if (! gfilter || ! gfilter->map[RMAP_IN].name
4294 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004295 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004296 filter->map[RMAP_IN].name, VTY_NEWLINE);
4297 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004298 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004299 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4300 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4301 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4302 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4303 if (filter->map[RMAP_EXPORT].name)
4304 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4305 || strcmp (filter->map[RMAP_EXPORT].name,
4306 gfilter->map[RMAP_EXPORT].name) != 0)
4307 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4308 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004309
4310 /* unsuppress-map */
4311 if (filter->usmap.name && ! gfilter)
4312 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4313 filter->usmap.name, VTY_NEWLINE);
4314
4315 /* filter-list. */
4316 if (filter->aslist[in].name)
4317 if (! gfilter || ! gfilter->aslist[in].name
4318 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4319 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4320 filter->aslist[in].name, VTY_NEWLINE);
4321 if (filter->aslist[out].name && ! gfilter)
4322 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4323 filter->aslist[out].name, VTY_NEWLINE);
4324}
4325
4326/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004327static void
paul718e3742002-12-13 20:15:29 +00004328bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4329 struct peer *peer, afi_t afi, safi_t safi)
4330{
4331 struct bgp_filter *filter;
4332 struct peer *g_peer = NULL;
4333 char buf[SU_ADDRSTRLEN];
4334 char *addr;
4335
4336 filter = &peer->filter[afi][safi];
4337 addr = peer->host;
4338 if (peer_group_active (peer))
4339 g_peer = peer->group->conf;
4340
4341 /************************************
4342 ****** Global to the neighbor ******
4343 ************************************/
4344 if (afi == AFI_IP && safi == SAFI_UNICAST)
4345 {
4346 /* remote-as. */
4347 if (! peer_group_active (peer))
4348 {
4349 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4350 vty_out (vty, " neighbor %s peer-group%s", addr,
4351 VTY_NEWLINE);
4352 if (peer->as)
4353 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4354 VTY_NEWLINE);
4355 }
4356 else
4357 {
4358 if (! g_peer->as)
4359 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4360 VTY_NEWLINE);
4361 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4362 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4363 peer->group->name, VTY_NEWLINE);
4364 }
4365
4366 /* local-as. */
4367 if (peer->change_local_as)
4368 if (! peer_group_active (peer))
4369 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4370 peer->change_local_as,
4371 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4372 " no-prepend" : "", VTY_NEWLINE);
4373
4374 /* Description. */
4375 if (peer->desc)
4376 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4377 VTY_NEWLINE);
4378
4379 /* Shutdown. */
4380 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4381 if (! peer_group_active (peer) ||
4382 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4383 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4384
4385 /* BGP port. */
4386 if (peer->port != BGP_PORT_DEFAULT)
4387 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4388 VTY_NEWLINE);
4389
4390 /* Local interface name. */
4391 if (peer->ifname)
4392 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4393 VTY_NEWLINE);
4394
4395 /* Passive. */
4396 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4397 if (! peer_group_active (peer) ||
4398 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4399 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4400
4401 /* EBGP multihop. */
4402 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4403 if (! peer_group_active (peer) ||
4404 g_peer->ttl != peer->ttl)
4405 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4406 VTY_NEWLINE);
4407
hasso6ffd2072005-02-02 14:50:11 +00004408 /* disable-connected-check. */
4409 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004410 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004411 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4412 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004413
4414 /* Update-source. */
4415 if (peer->update_if)
4416 if (! peer_group_active (peer) || ! g_peer->update_if
4417 || strcmp (g_peer->update_if, peer->update_if) != 0)
4418 vty_out (vty, " neighbor %s update-source %s%s", addr,
4419 peer->update_if, VTY_NEWLINE);
4420 if (peer->update_source)
4421 if (! peer_group_active (peer) || ! g_peer->update_source
4422 || sockunion_cmp (g_peer->update_source,
4423 peer->update_source) != 0)
4424 vty_out (vty, " neighbor %s update-source %s%s", addr,
4425 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4426 VTY_NEWLINE);
4427
paul718e3742002-12-13 20:15:29 +00004428 /* advertisement-interval */
4429 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4430 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4431 addr, peer->v_routeadv, VTY_NEWLINE);
4432
4433 /* timers. */
4434 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4435 && ! peer_group_active (peer))
4436 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4437 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4438
4439 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4440 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4441 peer->connect, VTY_NEWLINE);
4442
4443 /* Default weight. */
4444 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4445 if (! peer_group_active (peer) ||
4446 g_peer->weight != peer->weight)
4447 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4448 VTY_NEWLINE);
4449
paul718e3742002-12-13 20:15:29 +00004450 /* Dynamic capability. */
4451 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4452 if (! peer_group_active (peer) ||
4453 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4454 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4455 VTY_NEWLINE);
4456
4457 /* dont capability negotiation. */
4458 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4459 if (! peer_group_active (peer) ||
4460 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4461 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4462 VTY_NEWLINE);
4463
4464 /* override capability negotiation. */
4465 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4466 if (! peer_group_active (peer) ||
4467 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4468 vty_out (vty, " neighbor %s override-capability%s", addr,
4469 VTY_NEWLINE);
4470
4471 /* strict capability negotiation. */
4472 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4473 if (! peer_group_active (peer) ||
4474 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4475 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4476 VTY_NEWLINE);
4477
4478 if (! peer_group_active (peer))
4479 {
4480 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4481 {
4482 if (peer->afc[AFI_IP][SAFI_UNICAST])
4483 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4484 }
4485 else
4486 {
4487 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4488 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4489 }
4490 }
4491 }
4492
4493
4494 /************************************
4495 ****** Per AF to the neighbor ******
4496 ************************************/
4497
4498 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4499 {
4500 if (peer->af_group[afi][safi])
4501 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4502 peer->group->name, VTY_NEWLINE);
4503 else
4504 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4505 }
4506
4507 /* ORF capability. */
4508 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4509 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4510 if (! peer->af_group[afi][safi])
4511 {
4512 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4513
4514 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4515 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4516 vty_out (vty, " both");
4517 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4518 vty_out (vty, " send");
4519 else
4520 vty_out (vty, " receive");
4521 vty_out (vty, "%s", VTY_NEWLINE);
4522 }
4523
4524 /* Route reflector client. */
4525 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4526 && ! peer->af_group[afi][safi])
4527 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4528 VTY_NEWLINE);
4529
4530 /* Nexthop self. */
4531 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4532 && ! peer->af_group[afi][safi])
4533 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4534
4535 /* Remove private AS. */
4536 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4537 && ! peer->af_group[afi][safi])
4538 vty_out (vty, " neighbor %s remove-private-AS%s",
4539 addr, VTY_NEWLINE);
4540
4541 /* send-community print. */
4542 if (! peer->af_group[afi][safi])
4543 {
4544 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4545 {
4546 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4547 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4548 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4549 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4550 vty_out (vty, " neighbor %s send-community extended%s",
4551 addr, VTY_NEWLINE);
4552 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4553 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4554 }
4555 else
4556 {
4557 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4558 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4559 vty_out (vty, " no neighbor %s send-community both%s",
4560 addr, VTY_NEWLINE);
4561 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4562 vty_out (vty, " no neighbor %s send-community extended%s",
4563 addr, VTY_NEWLINE);
4564 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4565 vty_out (vty, " no neighbor %s send-community%s",
4566 addr, VTY_NEWLINE);
4567 }
4568 }
4569
4570 /* Default information */
4571 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4572 && ! peer->af_group[afi][safi])
4573 {
4574 vty_out (vty, " neighbor %s default-originate", addr);
4575 if (peer->default_rmap[afi][safi].name)
4576 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4577 vty_out (vty, "%s", VTY_NEWLINE);
4578 }
4579
4580 /* Soft reconfiguration inbound. */
4581 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4582 if (! peer->af_group[afi][safi] ||
4583 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4584 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4585 VTY_NEWLINE);
4586
4587 /* maximum-prefix. */
4588 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4589 if (! peer->af_group[afi][safi]
4590 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004591 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004592 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4593 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004594 {
hasso0a486e52005-02-01 20:57:17 +00004595 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4596 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4597 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4598 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4599 vty_out (vty, " warning-only");
4600 if (peer->pmax_restart[afi][safi])
4601 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4602 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004603 }
paul718e3742002-12-13 20:15:29 +00004604
4605 /* Route server client. */
4606 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4607 && ! peer->af_group[afi][safi])
4608 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4609
4610 /* Allow AS in. */
4611 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4612 if (! peer_group_active (peer)
4613 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4614 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4615 {
4616 if (peer->allowas_in[afi][safi] == 3)
4617 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4618 else
4619 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4620 peer->allowas_in[afi][safi], VTY_NEWLINE);
4621 }
4622
4623 /* Filter. */
4624 bgp_config_write_filter (vty, peer, afi, safi);
4625
4626 /* atribute-unchanged. */
4627 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4628 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4629 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4630 && ! peer->af_group[afi][safi])
4631 {
4632 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4633 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4634 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4635 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4636 else
4637 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4638 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4639 " as-path" : "",
4640 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4641 " next-hop" : "",
4642 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4643 " med" : "", VTY_NEWLINE);
4644 }
4645}
4646
4647/* Display "address-family" configuration header. */
4648void
4649bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4650 int *write)
4651{
4652 if (*write)
4653 return;
4654
4655 if (afi == AFI_IP && safi == SAFI_UNICAST)
4656 return;
4657
4658 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4659
4660 if (afi == AFI_IP)
4661 {
4662 if (safi == SAFI_MULTICAST)
4663 vty_out (vty, "ipv4 multicast");
4664 else if (safi == SAFI_MPLS_VPN)
4665 vty_out (vty, "vpnv4 unicast");
4666 }
4667 else if (afi == AFI_IP6)
4668 vty_out (vty, "ipv6");
4669
4670 vty_out (vty, "%s", VTY_NEWLINE);
4671
4672 *write = 1;
4673}
4674
4675/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004676static int
paul718e3742002-12-13 20:15:29 +00004677bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4678 safi_t safi)
4679{
4680 int write = 0;
4681 struct peer *peer;
4682 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004683 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004684
4685 bgp_config_write_network (vty, bgp, afi, safi, &write);
4686
4687 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4688
paul1eb8ef22005-04-07 07:30:20 +00004689 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004690 {
4691 if (group->conf->afc[afi][safi])
4692 {
4693 bgp_config_write_family_header (vty, afi, safi, &write);
4694 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4695 }
4696 }
paul1eb8ef22005-04-07 07:30:20 +00004697 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004698 {
4699 if (peer->afc[afi][safi])
4700 {
4701 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4702 {
4703 bgp_config_write_family_header (vty, afi, safi, &write);
4704 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4705 }
4706 }
4707 }
4708 if (write)
4709 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4710
4711 return write;
4712}
4713
4714int
4715bgp_config_write (struct vty *vty)
4716{
4717 int write = 0;
4718 struct bgp *bgp;
4719 struct peer_group *group;
4720 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004721 struct listnode *node, *nnode;
4722 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004723
4724 /* BGP Multiple instance. */
4725 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4726 {
4727 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4728 write++;
4729 }
4730
4731 /* BGP Config type. */
4732 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4733 {
4734 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4735 write++;
4736 }
4737
4738 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004739 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004740 {
4741 if (write)
4742 vty_out (vty, "!%s", VTY_NEWLINE);
4743
4744 /* Router bgp ASN */
4745 vty_out (vty, "router bgp %d", bgp->as);
4746
4747 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4748 {
4749 if (bgp->name)
4750 vty_out (vty, " view %s", bgp->name);
4751 }
4752 vty_out (vty, "%s", VTY_NEWLINE);
4753
4754 /* No Synchronization */
4755 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4756 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4757
4758 /* BGP fast-external-failover. */
4759 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4760 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4761
4762 /* BGP router ID. */
4763 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4764 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4765 VTY_NEWLINE);
4766
paul848973c2003-08-13 00:32:49 +00004767 /* BGP log-neighbor-changes. */
4768 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4769 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4770
paul718e3742002-12-13 20:15:29 +00004771 /* BGP configuration. */
4772 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4773 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4774
4775 /* BGP default ipv4-unicast. */
4776 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4777 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4778
4779 /* BGP default local-preference. */
4780 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4781 vty_out (vty, " bgp default local-preference %d%s",
4782 bgp->default_local_pref, VTY_NEWLINE);
4783
4784 /* BGP client-to-client reflection. */
4785 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4786 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4787
4788 /* BGP cluster ID. */
4789 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4790 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4791 VTY_NEWLINE);
4792
hassoe0701b72004-05-20 09:19:34 +00004793 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004794 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004795 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4796 VTY_NEWLINE);
4797
4798 /* Confederation peer */
4799 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004800 {
hassoe0701b72004-05-20 09:19:34 +00004801 int i;
paul718e3742002-12-13 20:15:29 +00004802
hassoe0701b72004-05-20 09:19:34 +00004803 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004804
hassoe0701b72004-05-20 09:19:34 +00004805 for (i = 0; i < bgp->confed_peers_cnt; i++)
4806 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004807
hassoe0701b72004-05-20 09:19:34 +00004808 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004809 }
4810
4811 /* BGP enforce-first-as. */
4812 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4813 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4814
4815 /* BGP deterministic-med. */
4816 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4817 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004818
4819 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004820 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4821 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4822 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004823 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4824 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4825
paul718e3742002-12-13 20:15:29 +00004826 /* BGP bestpath method. */
4827 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4828 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004829 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4830 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004831 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4832 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4833 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4834 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4835 {
4836 vty_out (vty, " bgp bestpath med");
4837 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4838 vty_out (vty, " confed");
4839 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4840 vty_out (vty, " missing-as-worst");
4841 vty_out (vty, "%s", VTY_NEWLINE);
4842 }
4843
4844 /* BGP network import check. */
4845 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4846 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4847
4848 /* BGP scan interval. */
4849 bgp_config_write_scan_time (vty);
4850
4851 /* BGP flag dampening. */
4852 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4853 BGP_CONFIG_DAMPENING))
4854 bgp_config_write_damp (vty);
4855
4856 /* BGP static route configuration. */
4857 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4858
4859 /* BGP redistribute configuration. */
4860 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4861
4862 /* BGP timers configuration. */
4863 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4864 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4865 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4866 bgp->default_holdtime, VTY_NEWLINE);
4867
4868 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004869 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004870 {
4871 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4872 }
4873
4874 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004875 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004876 {
4877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4878 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4879 }
4880
4881 /* Distance configuration. */
4882 bgp_config_write_distance (vty, bgp);
4883
4884 /* No auto-summary */
4885 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4886 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4887
4888 /* IPv4 multicast configuration. */
4889 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4890
4891 /* IPv4 VPN configuration. */
4892 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4893
4894 /* IPv6 unicast configuration. */
4895 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4896
4897 write++;
4898 }
4899 return write;
4900}
4901
4902void
paul94f2b392005-06-28 12:44:16 +00004903bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00004904{
4905 memset (&bgp_master, 0, sizeof (struct bgp_master));
4906
4907 bm = &bgp_master;
4908 bm->bgp = list_new ();
4909 bm->port = BGP_PORT_DEFAULT;
4910 bm->master = thread_master_create ();
4911 bm->start_time = time (NULL);
4912}
paul200df112005-06-01 11:17:05 +00004913
paul718e3742002-12-13 20:15:29 +00004914
4915void
paul94f2b392005-06-28 12:44:16 +00004916bgp_init (void)
paul718e3742002-12-13 20:15:29 +00004917{
paul718e3742002-12-13 20:15:29 +00004918 /* BGP VTY commands installation. */
4919 bgp_vty_init ();
4920
4921 /* Create BGP server socket. */
4922 bgp_socket (NULL, bm->port);
4923
4924 /* Init zebra. */
4925 bgp_zebra_init ();
4926
4927 /* BGP inits. */
4928 bgp_attr_init ();
4929 bgp_debug_init ();
4930 bgp_dump_init ();
4931 bgp_route_init ();
4932 bgp_route_map_init ();
4933 bgp_scan_init ();
4934 bgp_mplsvpn_init ();
4935
4936 /* Access list initialize. */
4937 access_list_init ();
4938 access_list_add_hook (peer_distribute_update);
4939 access_list_delete_hook (peer_distribute_update);
4940
4941 /* Filter list initialize. */
4942 bgp_filter_init ();
4943 as_list_add_hook (peer_aslist_update);
4944 as_list_delete_hook (peer_aslist_update);
4945
4946 /* Prefix list initialize.*/
4947 prefix_list_init ();
4948 prefix_list_add_hook (peer_prefix_list_update);
4949 prefix_list_delete_hook (peer_prefix_list_update);
4950
4951 /* Community list initialize. */
4952 bgp_clist = community_list_init ();
4953
4954#ifdef HAVE_SNMP
4955 bgp_snmp_init ();
4956#endif /* HAVE_SNMP */
4957}
paul545acaf2004-04-20 15:13:15 +00004958
4959void
4960bgp_terminate ()
4961{
paul545acaf2004-04-20 15:13:15 +00004962 struct bgp *bgp;
4963 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004964 struct listnode *node, *nnode;
4965 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004966
paul1eb8ef22005-04-07 07:30:20 +00004967 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4968 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00004969 if (peer->status == Established)
4970 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4971 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00004972
paul545acaf2004-04-20 15:13:15 +00004973 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00004974 if (bm->process_main_queue)
4975 work_queue_free (bm->process_main_queue);
4976 if (bm->process_rsclient_queue)
4977 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00004978}
4979