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