blob: 01cabae0c21bf880716ee9b6d1f63c2ae309f9f5 [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{
Paul Jakmaca058a32006-09-14 02:58:49 +0000690 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700691
692 bgp_unlock(peer->bgp);
693
Paul Jakmaca058a32006-09-14 02:58:49 +0000694 /* this /ought/ to have been done already through bgp_stop earlier,
695 * but just to be sure..
696 */
697 bgp_timer_set (peer);
698 BGP_READ_OFF (peer->t_read);
699 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000700 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000701
paul200df112005-06-01 11:17:05 +0000702 if (peer->desc)
703 XFREE (MTYPE_PEER_DESC, peer->desc);
704
705 /* Free allocated host character. */
706 if (peer->host)
707 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
708
709 /* Update source configuration. */
710 if (peer->update_source)
711 sockunion_free (peer->update_source);
712
713 if (peer->update_if)
714 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000715
716 if (peer->clear_node_queue)
717 work_queue_free (peer->clear_node_queue);
718
Paul Jakmaca058a32006-09-14 02:58:49 +0000719 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000720 memset (peer, 0, sizeof (struct peer));
721
722 XFREE (MTYPE_BGP_PEER, peer);
723}
724
725/* increase reference count on a struct peer */
726struct peer *
727peer_lock (struct peer *peer)
728{
729 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000730
paul200df112005-06-01 11:17:05 +0000731 peer->lock++;
732
733 return peer;
734}
735
736/* decrease reference count on a struct peer
737 * struct peer is freed and NULL returned if last reference
738 */
739struct peer *
740peer_unlock (struct peer *peer)
741{
742 assert (peer && (peer->lock > 0));
743
744 peer->lock--;
745
746 if (peer->lock == 0)
747 {
748#if 0
749 zlog_debug ("unlocked and freeing");
750 zlog_backtrace (LOG_DEBUG);
751#endif
752 peer_free (peer);
753 return NULL;
754 }
755
756#if 0
757 if (peer->lock == 1)
758 {
759 zlog_debug ("unlocked to 1");
760 zlog_backtrace (LOG_DEBUG);
761 }
762#endif
763
764 return peer;
765}
766
767/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000768static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000769peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000770{
771 afi_t afi;
772 safi_t safi;
773 struct peer *peer;
774 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000775
776 /* bgp argument is absolutely required */
777 assert (bgp);
778 if (!bgp)
779 return NULL;
780
paul718e3742002-12-13 20:15:29 +0000781 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000782 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000783
784 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000785 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000786 peer->v_start = BGP_INIT_START_TIMER;
787 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
788 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
789 peer->status = Idle;
790 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000791 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000792 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000793 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000794 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700795 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000796
797 /* Set default flags. */
798 for (afi = AFI_IP; afi < AFI_MAX; afi++)
799 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
800 {
801 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
802 {
803 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
804 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
805 }
806 peer->orf_plist[afi][safi] = NULL;
807 }
808 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
809
810 /* Create buffers. */
811 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
812 peer->obuf = stream_fifo_new ();
813 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
814
815 bgp_sync_init (peer);
816
817 /* Get service port number. */
818 sp = getservbyname ("bgp", "tcp");
819 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
820
821 return peer;
822}
823
824/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000825static struct peer *
paul718e3742002-12-13 20:15:29 +0000826peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
827 as_t remote_as, afi_t afi, safi_t safi)
828{
829 int active;
830 struct peer *peer;
831 char buf[SU_ADDRSTRLEN];
832
Paul Jakma6f585442006-10-22 19:13:07 +0000833 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000834 peer->su = *su;
835 peer->local_as = local_as;
836 peer->as = remote_as;
837 peer->local_id = bgp->router_id;
838 peer->v_holdtime = bgp->default_holdtime;
839 peer->v_keepalive = bgp->default_keepalive;
840 if (peer_sort (peer) == BGP_PEER_IBGP)
841 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
842 else
843 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000844
845 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000846 listnode_add_sort (bgp->peer, peer);
847
848 active = peer_active (peer);
849
850 if (afi && safi)
851 peer->afc[afi][safi] = 1;
852
853 /* Last read time set */
854 peer->readtime = time (NULL);
855
paul848973c2003-08-13 00:32:49 +0000856 /* Last reset time set */
857 peer->resettime = time (NULL);
858
paul718e3742002-12-13 20:15:29 +0000859 /* Default TTL set. */
860 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
861
862 /* Make peer's address string. */
863 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000864 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000865
866 /* Set up peer's events and timers. */
867 if (! active && peer_active (peer))
868 bgp_timer_set (peer);
869
870 return peer;
871}
872
pauleb821182004-05-01 08:44:08 +0000873/* Make accept BGP peer. Called from bgp_accept (). */
874struct peer *
875peer_create_accept (struct bgp *bgp)
876{
877 struct peer *peer;
878
Paul Jakma6f585442006-10-22 19:13:07 +0000879 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000880
881 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000882 listnode_add_sort (bgp->peer, peer);
883
884 return peer;
885}
886
paul718e3742002-12-13 20:15:29 +0000887/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000888static void
paul718e3742002-12-13 20:15:29 +0000889peer_as_change (struct peer *peer, as_t as)
890{
891 int type;
892
893 /* Stop peer. */
894 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
895 {
896 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000897 {
898 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
901 }
paul718e3742002-12-13 20:15:29 +0000902 else
903 BGP_EVENT_ADD (peer, BGP_Stop);
904 }
905 type = peer_sort (peer);
906 peer->as = as;
907
paul848973c2003-08-13 00:32:49 +0000908 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
909 && ! bgp_confederation_peers_check (peer->bgp, as)
910 && peer->bgp->as != as)
911 peer->local_as = peer->bgp->confed_id;
912 else
913 peer->local_as = peer->bgp->as;
914
paul718e3742002-12-13 20:15:29 +0000915 /* Advertisement-interval reset */
916 if (peer_sort (peer) == BGP_PEER_IBGP)
917 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
918 else
919 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
920
921 /* TTL reset */
922 if (peer_sort (peer) == BGP_PEER_IBGP)
923 peer->ttl = 255;
924 else if (type == BGP_PEER_IBGP)
925 peer->ttl = 1;
926
927 /* reflector-client reset */
928 if (peer_sort (peer) != BGP_PEER_IBGP)
929 {
930 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
931 PEER_FLAG_REFLECTOR_CLIENT);
932 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
933 PEER_FLAG_REFLECTOR_CLIENT);
934 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
935 PEER_FLAG_REFLECTOR_CLIENT);
936 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
937 PEER_FLAG_REFLECTOR_CLIENT);
938 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
939 PEER_FLAG_REFLECTOR_CLIENT);
940 }
941
942 /* local-as reset */
943 if (peer_sort (peer) != BGP_PEER_EBGP)
944 {
945 peer->change_local_as = 0;
946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
947 }
948}
949
950/* If peer does not exist, create new one. If peer already exists,
951 set AS number to the peer. */
952int
953peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
954 afi_t afi, safi_t safi)
955{
956 struct peer *peer;
957 as_t local_as;
958
959 peer = peer_lookup (bgp, su);
960
961 if (peer)
962 {
963 /* When this peer is a member of peer-group. */
964 if (peer->group)
965 {
966 if (peer->group->conf->as)
967 {
968 /* Return peer group's AS number. */
969 *as = peer->group->conf->as;
970 return BGP_ERR_PEER_GROUP_MEMBER;
971 }
972 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
973 {
974 if (bgp->as != *as)
975 {
976 *as = peer->as;
977 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
978 }
979 }
980 else
981 {
982 if (bgp->as == *as)
983 {
984 *as = peer->as;
985 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
986 }
987 }
988 }
989
990 /* Existing peer's AS number change. */
991 if (peer->as != *as)
992 peer_as_change (peer, *as);
993 }
994 else
995 {
996
997 /* If the peer is not part of our confederation, and its not an
998 iBGP peer then spoof the source AS */
999 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1000 && ! bgp_confederation_peers_check (bgp, *as)
1001 && bgp->as != *as)
1002 local_as = bgp->confed_id;
1003 else
1004 local_as = bgp->as;
1005
1006 /* If this is IPv4 unicast configuration and "no bgp default
1007 ipv4-unicast" is specified. */
1008
1009 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1010 && afi == AFI_IP && safi == SAFI_UNICAST)
1011 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1012 else
1013 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1014 }
1015
1016 return 0;
1017}
1018
1019/* Activate the peer or peer group for specified AFI and SAFI. */
1020int
1021peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1022{
1023 int active;
1024
1025 if (peer->afc[afi][safi])
1026 return 0;
1027
1028 /* Activate the address family configuration. */
1029 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1030 peer->afc[afi][safi] = 1;
1031 else
1032 {
1033 active = peer_active (peer);
1034
1035 peer->afc[afi][safi] = 1;
1036
1037 if (! active && peer_active (peer))
1038 bgp_timer_set (peer);
1039 else
1040 {
1041 if (peer->status == Established)
1042 {
1043 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1044 {
1045 peer->afc_adv[afi][safi] = 1;
1046 bgp_capability_send (peer, afi, safi,
1047 CAPABILITY_CODE_MP,
1048 CAPABILITY_ACTION_SET);
1049 if (peer->afc_recv[afi][safi])
1050 {
1051 peer->afc_nego[afi][safi] = 1;
1052 bgp_announce_route (peer, afi, safi);
1053 }
1054 }
1055 else
hassoe0701b72004-05-20 09:19:34 +00001056 {
1057 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1058 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1059 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1060 }
paul718e3742002-12-13 20:15:29 +00001061 }
1062 }
1063 }
1064 return 0;
1065}
1066
1067int
1068peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1069{
1070 struct peer_group *group;
1071 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001072 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001073
1074 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1075 {
1076 group = peer->group;
1077
paul1eb8ef22005-04-07 07:30:20 +00001078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001079 {
1080 if (peer1->af_group[afi][safi])
1081 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1082 }
1083 }
1084 else
1085 {
1086 if (peer->af_group[afi][safi])
1087 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1088 }
1089
1090 if (! peer->afc[afi][safi])
1091 return 0;
1092
1093 /* De-activate the address family configuration. */
1094 peer->afc[afi][safi] = 0;
1095 peer_af_flag_reset (peer, afi, safi);
1096
1097 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1098 {
1099 if (peer->status == Established)
1100 {
1101 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1102 {
1103 peer->afc_adv[afi][safi] = 0;
1104 peer->afc_nego[afi][safi] = 0;
1105
1106 if (peer_active_nego (peer))
1107 {
1108 bgp_capability_send (peer, afi, safi,
1109 CAPABILITY_CODE_MP,
1110 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001111 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001112 peer->pcount[afi][safi] = 0;
1113 }
1114 else
hassoe0701b72004-05-20 09:19:34 +00001115 {
1116 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1117 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1118 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1119 }
paul718e3742002-12-13 20:15:29 +00001120 }
1121 else
hassoe0701b72004-05-20 09:19:34 +00001122 {
1123 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1124 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1125 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1126 }
paul718e3742002-12-13 20:15:29 +00001127 }
1128 }
1129 return 0;
1130}
1131
hasso93406d82005-02-02 14:40:33 +00001132void
1133peer_nsf_stop (struct peer *peer)
1134{
1135 afi_t afi;
1136 safi_t safi;
1137
1138 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1139 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1140
1141 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1142 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1143 peer->nsf[afi][safi] = 0;
1144
1145 if (peer->t_gr_restart)
1146 {
1147 BGP_TIMER_OFF (peer->t_gr_restart);
1148 if (BGP_DEBUG (events, EVENTS))
1149 zlog_debug ("%s graceful restart timer stopped", peer->host);
1150 }
1151 if (peer->t_gr_stale)
1152 {
1153 BGP_TIMER_OFF (peer->t_gr_stale);
1154 if (BGP_DEBUG (events, EVENTS))
1155 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1156 }
1157 bgp_clear_route_all (peer);
1158}
1159
Paul Jakmaca058a32006-09-14 02:58:49 +00001160/* Delete peer from confguration.
1161 *
1162 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1163 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1164 *
1165 * This function /should/ take care to be idempotent, to guard against
1166 * it being called multiple times through stray events that come in
1167 * that happen to result in this function being called again. That
1168 * said, getting here for a "Deleted" peer is a bug in the neighbour
1169 * FSM.
1170 */
paul718e3742002-12-13 20:15:29 +00001171int
1172peer_delete (struct peer *peer)
1173{
1174 int i;
1175 afi_t afi;
1176 safi_t safi;
1177 struct bgp *bgp;
1178 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001179 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001180
Paul Jakmaca058a32006-09-14 02:58:49 +00001181 assert (peer->status != Deleted);
1182
paul718e3742002-12-13 20:15:29 +00001183 bgp = peer->bgp;
1184
hasso93406d82005-02-02 14:40:33 +00001185 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1186 peer_nsf_stop (peer);
1187
Chris Caputo228da422009-07-18 05:44:03 +00001188 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001189 relationship. */
1190 if (peer->group)
1191 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001192 if ((pn = listnode_lookup (peer->group->peer, peer)))
1193 {
1194 peer = peer_unlock (peer); /* group->peer list reference */
1195 list_delete_node (peer->group->peer, pn);
1196 }
paul718e3742002-12-13 20:15:29 +00001197 peer->group = NULL;
1198 }
paul200df112005-06-01 11:17:05 +00001199
paul718e3742002-12-13 20:15:29 +00001200 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001201 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1202 * executed after peer structure is deleted.
1203 */
hassoe0701b72004-05-20 09:19:34 +00001204 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001205 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001206 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001207
1208 /* Password configuration */
1209 if (peer->password)
1210 {
1211 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1212 peer->password = NULL;
1213
1214 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1215 bgp_md5_set (peer);
1216 }
1217
Paul Jakmaca058a32006-09-14 02:58:49 +00001218 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001221 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1222 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001223 {
Chris Caputo228da422009-07-18 05:44:03 +00001224 peer_unlock (peer); /* bgp peer list reference */
1225 list_delete_node (bgp->peer, pn);
1226 }
paul200df112005-06-01 11:17:05 +00001227
Chris Caputo228da422009-07-18 05:44:03 +00001228 if (peer_rsclient_active (peer)
1229 && (pn = listnode_lookup (bgp->rsclient, peer)))
1230 {
1231 peer_unlock (peer); /* rsclient list reference */
1232 list_delete_node (bgp->rsclient, pn);
1233
1234 /* Clear our own rsclient ribs. */
1235 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1236 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1237 if (CHECK_FLAG(peer->af_flags[afi][safi],
1238 PEER_FLAG_RSERVER_CLIENT))
1239 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001240 }
1241
1242 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1243 member of a peer_group. */
1244 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1245 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1246 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001247 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001248
paul200df112005-06-01 11:17:05 +00001249 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001250 if (peer->ibuf)
1251 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001252 if (peer->obuf)
1253 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001254 if (peer->work)
1255 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001256 peer->obuf = NULL;
1257 peer->work = peer->ibuf = NULL;
1258
paul718e3742002-12-13 20:15:29 +00001259 /* Local and remote addresses. */
1260 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001261 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001262 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001263 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001264 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001265
paul718e3742002-12-13 20:15:29 +00001266 /* Free filter related memory. */
1267 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1268 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1269 {
1270 filter = &peer->filter[afi][safi];
1271
1272 for (i = FILTER_IN; i < FILTER_MAX; i++)
1273 {
1274 if (filter->dlist[i].name)
1275 free (filter->dlist[i].name);
1276 if (filter->plist[i].name)
1277 free (filter->plist[i].name);
1278 if (filter->aslist[i].name)
1279 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001280
1281 filter->dlist[i].name = NULL;
1282 filter->plist[i].name = NULL;
1283 filter->aslist[i].name = NULL;
1284 }
1285 for (i = RMAP_IN; i < RMAP_MAX; i++)
1286 {
paul718e3742002-12-13 20:15:29 +00001287 if (filter->map[i].name)
1288 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001289 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001290 }
1291
1292 if (filter->usmap.name)
1293 free (filter->usmap.name);
1294
1295 if (peer->default_rmap[afi][safi].name)
1296 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001297
1298 filter->usmap.name = NULL;
1299 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001300 }
paul200df112005-06-01 11:17:05 +00001301
1302 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001303
1304 return 0;
1305}
1306
paul94f2b392005-06-28 12:44:16 +00001307static int
paul718e3742002-12-13 20:15:29 +00001308peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1309{
1310 return strcmp (g1->name, g2->name);
1311}
1312
1313/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001314static int
paul718e3742002-12-13 20:15:29 +00001315peer_group_active (struct peer *peer)
1316{
1317 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1318 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1319 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1320 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1321 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1322 return 1;
1323 return 0;
1324}
1325
1326/* Peer group cofiguration. */
1327static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001328peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001329{
1330 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1331 sizeof (struct peer_group));
1332}
1333
paul94f2b392005-06-28 12:44:16 +00001334static void
paul718e3742002-12-13 20:15:29 +00001335peer_group_free (struct peer_group *group)
1336{
1337 XFREE (MTYPE_PEER_GROUP, group);
1338}
1339
1340struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001341peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001342{
1343 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001344 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001345
paul1eb8ef22005-04-07 07:30:20 +00001346 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001347 {
1348 if (strcmp (group->name, name) == 0)
1349 return group;
1350 }
1351 return NULL;
1352}
1353
1354struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001355peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001356{
1357 struct peer_group *group;
1358
1359 group = peer_group_lookup (bgp, name);
1360 if (group)
1361 return group;
1362
1363 group = peer_group_new ();
1364 group->bgp = bgp;
1365 group->name = strdup (name);
1366 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001367 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001368 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1369 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001370 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001371 group->conf->group = group;
1372 group->conf->as = 0;
1373 group->conf->ttl = 1;
1374 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1375 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1376 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1377 group->conf->keepalive = 0;
1378 group->conf->holdtime = 0;
1379 group->conf->connect = 0;
1380 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1381 listnode_add_sort (bgp->group, group);
1382
1383 return 0;
1384}
1385
paul94f2b392005-06-28 12:44:16 +00001386static void
paul718e3742002-12-13 20:15:29 +00001387peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1388 afi_t afi, safi_t safi)
1389{
1390 int in = FILTER_IN;
1391 int out = FILTER_OUT;
1392 struct peer *conf;
1393 struct bgp_filter *pfilter;
1394 struct bgp_filter *gfilter;
1395
1396 conf = group->conf;
1397 pfilter = &peer->filter[afi][safi];
1398 gfilter = &conf->filter[afi][safi];
1399
1400 /* remote-as */
1401 if (conf->as)
1402 peer->as = conf->as;
1403
1404 /* remote-as */
1405 if (conf->change_local_as)
1406 peer->change_local_as = conf->change_local_as;
1407
1408 /* TTL */
1409 peer->ttl = conf->ttl;
1410
1411 /* Weight */
1412 peer->weight = conf->weight;
1413
1414 /* peer flags apply */
1415 peer->flags = conf->flags;
1416 /* peer af_flags apply */
1417 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1418 /* peer config apply */
1419 peer->config = conf->config;
1420
1421 /* peer timers apply */
1422 peer->holdtime = conf->holdtime;
1423 peer->keepalive = conf->keepalive;
1424 peer->connect = conf->connect;
1425 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1426 peer->v_connect = conf->connect;
1427 else
1428 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1429
1430 /* advertisement-interval reset */
1431 if (peer_sort (peer) == BGP_PEER_IBGP)
1432 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1433 else
1434 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1435
Paul Jakma0df7c912008-07-21 21:02:49 +00001436 /* password apply */
1437 if (peer->password)
1438 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1439
1440 if (conf->password)
1441 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1442 else
1443 peer->password = NULL;
1444
1445 bgp_md5_set (peer);
1446
paul718e3742002-12-13 20:15:29 +00001447 /* maximum-prefix */
1448 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001449 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001450 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001451
1452 /* allowas-in */
1453 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1454
paulfee0f4c2004-09-13 05:12:46 +00001455 /* route-server-client */
1456 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1457 {
1458 /* Make peer's RIB point to group's RIB. */
1459 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1460
1461 /* Import policy. */
1462 if (pfilter->map[RMAP_IMPORT].name)
1463 free (pfilter->map[RMAP_IMPORT].name);
1464 if (gfilter->map[RMAP_IMPORT].name)
1465 {
1466 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1467 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1468 }
1469 else
1470 {
1471 pfilter->map[RMAP_IMPORT].name = NULL;
1472 pfilter->map[RMAP_IMPORT].map = NULL;
1473 }
1474
1475 /* Export policy. */
1476 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1477 {
1478 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1479 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1480 }
1481 }
1482
paul718e3742002-12-13 20:15:29 +00001483 /* default-originate route-map */
1484 if (conf->default_rmap[afi][safi].name)
1485 {
1486 if (peer->default_rmap[afi][safi].name)
1487 free (peer->default_rmap[afi][safi].name);
1488 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1489 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1490 }
1491
1492 /* update-source apply */
1493 if (conf->update_source)
1494 {
1495 if (peer->update_source)
1496 sockunion_free (peer->update_source);
1497 if (peer->update_if)
1498 {
1499 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1500 peer->update_if = NULL;
1501 }
1502 peer->update_source = sockunion_dup (conf->update_source);
1503 }
1504 else if (conf->update_if)
1505 {
1506 if (peer->update_if)
1507 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1508 if (peer->update_source)
1509 {
1510 sockunion_free (peer->update_source);
1511 peer->update_source = NULL;
1512 }
1513 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1514 }
1515
1516 /* inbound filter apply */
1517 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1518 {
1519 if (pfilter->dlist[in].name)
1520 free (pfilter->dlist[in].name);
1521 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1522 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1523 }
1524 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1525 {
1526 if (pfilter->plist[in].name)
1527 free (pfilter->plist[in].name);
1528 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1529 pfilter->plist[in].plist = gfilter->plist[in].plist;
1530 }
1531 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1532 {
1533 if (pfilter->aslist[in].name)
1534 free (pfilter->aslist[in].name);
1535 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1536 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1537 }
paulfee0f4c2004-09-13 05:12:46 +00001538 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001539 {
paulfee0f4c2004-09-13 05:12:46 +00001540 if (pfilter->map[RMAP_IN].name)
1541 free (pfilter->map[RMAP_IN].name);
1542 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1543 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001544 }
1545
1546 /* outbound filter apply */
1547 if (gfilter->dlist[out].name)
1548 {
1549 if (pfilter->dlist[out].name)
1550 free (pfilter->dlist[out].name);
1551 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1552 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1553 }
1554 else
1555 {
1556 if (pfilter->dlist[out].name)
1557 free (pfilter->dlist[out].name);
1558 pfilter->dlist[out].name = NULL;
1559 pfilter->dlist[out].alist = NULL;
1560 }
1561 if (gfilter->plist[out].name)
1562 {
1563 if (pfilter->plist[out].name)
1564 free (pfilter->plist[out].name);
1565 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1566 pfilter->plist[out].plist = gfilter->plist[out].plist;
1567 }
1568 else
1569 {
1570 if (pfilter->plist[out].name)
1571 free (pfilter->plist[out].name);
1572 pfilter->plist[out].name = NULL;
1573 pfilter->plist[out].plist = NULL;
1574 }
1575 if (gfilter->aslist[out].name)
1576 {
1577 if (pfilter->aslist[out].name)
1578 free (pfilter->aslist[out].name);
1579 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1580 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1581 }
1582 else
1583 {
1584 if (pfilter->aslist[out].name)
1585 free (pfilter->aslist[out].name);
1586 pfilter->aslist[out].name = NULL;
1587 pfilter->aslist[out].aslist = NULL;
1588 }
paulfee0f4c2004-09-13 05:12:46 +00001589 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001590 {
paulfee0f4c2004-09-13 05:12:46 +00001591 if (pfilter->map[RMAP_OUT].name)
1592 free (pfilter->map[RMAP_OUT].name);
1593 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1594 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001595 }
1596 else
1597 {
paulfee0f4c2004-09-13 05:12:46 +00001598 if (pfilter->map[RMAP_OUT].name)
1599 free (pfilter->map[RMAP_OUT].name);
1600 pfilter->map[RMAP_OUT].name = NULL;
1601 pfilter->map[RMAP_OUT].map = NULL;
1602 }
1603
1604 /* RS-client's import/export route-maps. */
1605 if (gfilter->map[RMAP_IMPORT].name)
1606 {
1607 if (pfilter->map[RMAP_IMPORT].name)
1608 free (pfilter->map[RMAP_IMPORT].name);
1609 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1610 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1611 }
1612 else
1613 {
1614 if (pfilter->map[RMAP_IMPORT].name)
1615 free (pfilter->map[RMAP_IMPORT].name);
1616 pfilter->map[RMAP_IMPORT].name = NULL;
1617 pfilter->map[RMAP_IMPORT].map = NULL;
1618 }
1619 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1620 {
1621 if (pfilter->map[RMAP_EXPORT].name)
1622 free (pfilter->map[RMAP_EXPORT].name);
1623 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1624 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001625 }
1626
1627 if (gfilter->usmap.name)
1628 {
1629 if (pfilter->usmap.name)
1630 free (pfilter->usmap.name);
1631 pfilter->usmap.name = strdup (gfilter->usmap.name);
1632 pfilter->usmap.map = gfilter->usmap.map;
1633 }
1634 else
1635 {
1636 if (pfilter->usmap.name)
1637 free (pfilter->usmap.name);
1638 pfilter->usmap.name = NULL;
1639 pfilter->usmap.map = NULL;
1640 }
1641}
1642
1643/* Peer group's remote AS configuration. */
1644int
paulfd79ac92004-10-13 05:06:08 +00001645peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001646{
1647 struct peer_group *group;
1648 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001649 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001650
1651 group = peer_group_lookup (bgp, group_name);
1652 if (! group)
1653 return -1;
1654
1655 if (group->conf->as == *as)
1656 return 0;
1657
1658 /* When we setup peer-group AS number all peer group member's AS
1659 number must be updated to same number. */
1660 peer_as_change (group->conf, *as);
1661
paul1eb8ef22005-04-07 07:30:20 +00001662 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001663 {
1664 if (peer->as != *as)
1665 peer_as_change (peer, *as);
1666 }
1667
1668 return 0;
1669}
1670
1671int
1672peer_group_delete (struct peer_group *group)
1673{
1674 struct bgp *bgp;
1675 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001676 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001677
1678 bgp = group->bgp;
1679
paul1eb8ef22005-04-07 07:30:20 +00001680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001681 {
1682 peer->group = NULL;
1683 peer_delete (peer);
1684 }
1685 list_delete (group->peer);
1686
1687 free (group->name);
1688 group->name = NULL;
1689
1690 group->conf->group = NULL;
1691 peer_delete (group->conf);
1692
1693 /* Delete from all peer_group list. */
1694 listnode_delete (bgp->group, group);
1695
1696 peer_group_free (group);
1697
1698 return 0;
1699}
1700
1701int
1702peer_group_remote_as_delete (struct peer_group *group)
1703{
1704 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001705 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001706
1707 if (! group->conf->as)
1708 return 0;
1709
paul1eb8ef22005-04-07 07:30:20 +00001710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001711 {
1712 peer->group = NULL;
1713 peer_delete (peer);
1714 }
1715 list_delete_all_node (group->peer);
1716
1717 group->conf->as = 0;
1718
1719 return 0;
1720}
1721
1722/* Bind specified peer to peer group. */
1723int
1724peer_group_bind (struct bgp *bgp, union sockunion *su,
1725 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1726{
1727 struct peer *peer;
1728 int first_member = 0;
1729
1730 /* Check peer group's address family. */
1731 if (! group->conf->afc[afi][safi])
1732 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1733
1734 /* Lookup the peer. */
1735 peer = peer_lookup (bgp, su);
1736
1737 /* Create a new peer. */
1738 if (! peer)
1739 {
1740 if (! group->conf->as)
1741 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1742
1743 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1744 peer->group = group;
1745 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001746
Paul Jakmaca058a32006-09-14 02:58:49 +00001747 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001748 listnode_add (group->peer, peer);
1749 peer_group2peer_config_copy (group, peer, afi, safi);
1750
1751 return 0;
1752 }
1753
1754 /* When the peer already belongs to peer group, check the consistency. */
1755 if (peer->af_group[afi][safi])
1756 {
1757 if (strcmp (peer->group->name, group->name) != 0)
1758 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1759
1760 return 0;
1761 }
1762
1763 /* Check current peer group configuration. */
1764 if (peer_group_active (peer)
1765 && strcmp (peer->group->name, group->name) != 0)
1766 return BGP_ERR_PEER_GROUP_MISMATCH;
1767
1768 if (! group->conf->as)
1769 {
1770 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1771 && peer_sort (group->conf) != peer_sort (peer))
1772 {
1773 if (as)
1774 *as = peer->as;
1775 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1776 }
1777
1778 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1779 first_member = 1;
1780 }
1781
1782 peer->af_group[afi][safi] = 1;
1783 peer->afc[afi][safi] = 1;
1784 if (! peer->group)
1785 {
1786 peer->group = group;
paul200df112005-06-01 11:17:05 +00001787
Paul Jakmaca058a32006-09-14 02:58:49 +00001788 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001789 listnode_add (group->peer, peer);
1790 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001791 else
1792 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001793
1794 if (first_member)
1795 {
1796 /* Advertisement-interval reset */
1797 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1798 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1799 else
1800 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1801
1802 /* ebgp-multihop reset */
1803 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1804 group->conf->ttl = 255;
1805
1806 /* local-as reset */
1807 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1808 {
1809 group->conf->change_local_as = 0;
1810 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1811 }
1812 }
paulfee0f4c2004-09-13 05:12:46 +00001813
1814 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1815 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001816 struct listnode *pn;
1817
paulfee0f4c2004-09-13 05:12:46 +00001818 /* If it's not configured as RSERVER_CLIENT in any other address
1819 family, without being member of a peer_group, remove it from
1820 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001821 if (! peer_rsclient_active (peer)
1822 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001823 {
1824 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001825 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001826
1827 /* Clear our own rsclient rib for this afi/safi. */
1828 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001829 }
paulfee0f4c2004-09-13 05:12:46 +00001830
Paul Jakmab608d5b2008-07-02 02:12:07 +00001831 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001832
1833 /* Import policy. */
1834 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1835 {
1836 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1837 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1838 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1839 }
1840
1841 /* Export policy. */
1842 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1843 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1844 {
1845 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1846 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1847 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1848 }
1849 }
1850
paul718e3742002-12-13 20:15:29 +00001851 peer_group2peer_config_copy (group, peer, afi, safi);
1852
1853 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001854 {
1855 peer->last_reset = PEER_DOWN_RMAP_BIND;
1856 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1857 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1858 }
paul718e3742002-12-13 20:15:29 +00001859 else
1860 BGP_EVENT_ADD (peer, BGP_Stop);
1861
1862 return 0;
1863}
1864
1865int
1866peer_group_unbind (struct bgp *bgp, struct peer *peer,
1867 struct peer_group *group, afi_t afi, safi_t safi)
1868{
1869 if (! peer->af_group[afi][safi])
1870 return 0;
1871
1872 if (group != peer->group)
1873 return BGP_ERR_PEER_GROUP_MISMATCH;
1874
1875 peer->af_group[afi][safi] = 0;
1876 peer->afc[afi][safi] = 0;
1877 peer_af_flag_reset (peer, afi, safi);
1878
paulfee0f4c2004-09-13 05:12:46 +00001879 if (peer->rib[afi][safi])
1880 peer->rib[afi][safi] = NULL;
1881
paul718e3742002-12-13 20:15:29 +00001882 if (! peer_group_active (peer))
1883 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001884 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001885 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001886 listnode_delete (group->peer, peer);
1887 peer->group = NULL;
1888 if (group->conf->as)
1889 {
1890 peer_delete (peer);
1891 return 0;
1892 }
1893 peer_global_config_reset (peer);
1894 }
1895
1896 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001897 {
1898 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1901 }
paul718e3742002-12-13 20:15:29 +00001902 else
1903 BGP_EVENT_ADD (peer, BGP_Stop);
1904
1905 return 0;
1906}
1907
1908/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001909static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001910bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001911{
1912 struct bgp *bgp;
1913 afi_t afi;
1914 safi_t safi;
1915
paul200df112005-06-01 11:17:05 +00001916 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1917 return NULL;
1918
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001919 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001920 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001921 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001922
1923 bgp->peer = list_new ();
1924 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1925
1926 bgp->group = list_new ();
1927 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1928
paulfee0f4c2004-09-13 05:12:46 +00001929 bgp->rsclient = list_new ();
1930 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1931
paul718e3742002-12-13 20:15:29 +00001932 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1933 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1934 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001935 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1936 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1937 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001938 }
1939
1940 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1941 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1942 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001943 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1944 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001945
1946 bgp->as = *as;
1947
1948 if (name)
1949 bgp->name = strdup (name);
1950
1951 return bgp;
1952}
1953
1954/* Return first entry of BGP. */
1955struct bgp *
paul94f2b392005-06-28 12:44:16 +00001956bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001957{
1958 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001959 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001960 return NULL;
1961}
1962
1963/* Lookup BGP entry. */
1964struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001965bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001966{
1967 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001968 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001969
paul1eb8ef22005-04-07 07:30:20 +00001970 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001971 if (bgp->as == as
1972 && ((bgp->name == NULL && name == NULL)
1973 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1974 return bgp;
1975 return NULL;
1976}
1977
1978/* Lookup BGP structure by view name. */
1979struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001980bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001981{
1982 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001984
paul1eb8ef22005-04-07 07:30:20 +00001985 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001986 if ((bgp->name == NULL && name == NULL)
1987 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1988 return bgp;
1989 return NULL;
1990}
1991
1992/* Called from VTY commands. */
1993int
paulfd79ac92004-10-13 05:06:08 +00001994bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001995{
1996 struct bgp *bgp;
1997
1998 /* Multiple instance check. */
1999 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2000 {
2001 if (name)
2002 bgp = bgp_lookup_by_name (name);
2003 else
2004 bgp = bgp_get_default ();
2005
2006 /* Already exists. */
2007 if (bgp)
2008 {
2009 if (bgp->as != *as)
2010 {
2011 *as = bgp->as;
2012 return BGP_ERR_INSTANCE_MISMATCH;
2013 }
2014 *bgp_val = bgp;
2015 return 0;
2016 }
2017 }
2018 else
2019 {
2020 /* BGP instance name can not be specified for single instance. */
2021 if (name)
2022 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2023
2024 /* Get default BGP structure if exists. */
2025 bgp = bgp_get_default ();
2026
2027 if (bgp)
2028 {
2029 if (bgp->as != *as)
2030 {
2031 *as = bgp->as;
2032 return BGP_ERR_AS_MISMATCH;
2033 }
2034 *bgp_val = bgp;
2035 return 0;
2036 }
2037 }
2038
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002039 /* Create BGP server socket, if first instance. */
2040 if (list_isempty(bm->bgp))
2041 {
2042 if (bgp_socket (bm->port, bm->address) < 0)
2043 return BGP_ERR_INVALID_VALUE;
2044 }
2045
paul718e3742002-12-13 20:15:29 +00002046 bgp = bgp_create (as, name);
2047 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002048 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002049 *bgp_val = bgp;
2050
2051 return 0;
2052}
2053
2054/* Delete BGP instance. */
2055int
2056bgp_delete (struct bgp *bgp)
2057{
2058 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002059 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002060 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002061 struct listnode *next;
2062 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002063 int i;
2064
2065 /* Delete static route. */
2066 bgp_static_delete (bgp);
2067
2068 /* Unset redistribution. */
2069 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2070 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2071 if (i != ZEBRA_ROUTE_BGP)
2072 bgp_redistribute_unset (bgp, afi, i);
2073
paul1eb8ef22005-04-07 07:30:20 +00002074 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2075 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002076
Chris Caputo228da422009-07-18 05:44:03 +00002077 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2078 peer_group_delete (group);
2079
2080 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002081
2082 if (bgp->peer_self) {
2083 peer_delete(bgp->peer_self);
2084 bgp->peer_self = NULL;
2085 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002086
2087 /* Remove visibility via the master list - there may however still be
2088 * routes to be processed still referencing the struct bgp.
2089 */
2090 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002091 if (list_isempty(bm->bgp))
2092 bgp_close ();
2093
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002094 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002095
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002096 return 0;
2097}
2098
2099static void bgp_free (struct bgp *);
2100
2101void
2102bgp_lock (struct bgp *bgp)
2103{
2104 ++bgp->lock;
2105}
2106
2107void
2108bgp_unlock(struct bgp *bgp)
2109{
Chris Caputo228da422009-07-18 05:44:03 +00002110 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002111 if (--bgp->lock == 0)
2112 bgp_free (bgp);
2113}
2114
2115static void
2116bgp_free (struct bgp *bgp)
2117{
2118 afi_t afi;
2119 safi_t safi;
2120
2121 list_delete (bgp->group);
2122 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002123 list_delete (bgp->rsclient);
2124
paul718e3742002-12-13 20:15:29 +00002125 if (bgp->name)
2126 free (bgp->name);
2127
2128 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2129 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2130 {
2131 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002132 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002133 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002134 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002135 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002136 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002137 }
2138 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002139}
2140
2141struct peer *
2142peer_lookup (struct bgp *bgp, union sockunion *su)
2143{
2144 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002145 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002146
Steve Hillfc4dc592009-07-28 17:54:35 +01002147 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002148 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002149 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2150 if (sockunion_same (&peer->su, su)
2151 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2152 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002153 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002154 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002155 {
2156 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002157
Paul Jakma2158ad22009-07-28 18:10:55 +01002158 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2159 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2160 if (sockunion_same (&peer->su, su)
2161 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2162 return peer;
paul718e3742002-12-13 20:15:29 +00002163 }
2164 return NULL;
2165}
2166
2167struct peer *
2168peer_lookup_with_open (union sockunion *su, as_t remote_as,
2169 struct in_addr *remote_id, int *as)
2170{
2171 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002172 struct listnode *node, *nnode;
Steve Hillfc4dc592009-07-28 17:54:35 +01002173 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002174 struct bgp *bgp;
2175
Steve Hillfc4dc592009-07-28 17:54:35 +01002176 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002177 return NULL;
2178
Paul Jakma2158ad22009-07-28 18:10:55 +01002179 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2180 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2181 {
2182 if (sockunion_same (&peer->su, su)
2183 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2184 {
2185 if (peer->as == remote_as
2186 && peer->remote_id.s_addr == remote_id->s_addr)
2187 return peer;
2188 if (peer->as == remote_as)
2189 *as = 1;
2190 }
2191 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002192
paul1eb8ef22005-04-07 07:30:20 +00002193 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002194 {
pauleb821182004-05-01 08:44:08 +00002195 if (sockunion_same (&peer->su, su)
2196 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2197 {
2198 if (peer->as == remote_as
2199 && peer->remote_id.s_addr == 0)
2200 return peer;
2201 if (peer->as == remote_as)
2202 *as = 1;
2203 }
paul718e3742002-12-13 20:15:29 +00002204 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002205 }
paul718e3742002-12-13 20:15:29 +00002206 return NULL;
2207}
2208
2209/* If peer is configured at least one address family return 1. */
2210int
2211peer_active (struct peer *peer)
2212{
2213 if (peer->afc[AFI_IP][SAFI_UNICAST]
2214 || peer->afc[AFI_IP][SAFI_MULTICAST]
2215 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2216 || peer->afc[AFI_IP6][SAFI_UNICAST]
2217 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2218 return 1;
2219 return 0;
2220}
2221
2222/* If peer is negotiated at least one address family return 1. */
2223int
2224peer_active_nego (struct peer *peer)
2225{
2226 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2227 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2228 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2229 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2230 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2231 return 1;
2232 return 0;
2233}
2234
2235/* peer_flag_change_type. */
2236enum peer_change_type
2237{
2238 peer_change_none,
2239 peer_change_reset,
2240 peer_change_reset_in,
2241 peer_change_reset_out,
2242};
2243
paul94f2b392005-06-28 12:44:16 +00002244static void
paul718e3742002-12-13 20:15:29 +00002245peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2246 enum peer_change_type type)
2247{
2248 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2249 return;
2250
2251 if (type == peer_change_reset)
2252 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2253 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2254 else if (type == peer_change_reset_in)
2255 {
2256 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2257 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2258 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2259 else
2260 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2261 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2262 }
2263 else if (type == peer_change_reset_out)
2264 bgp_announce_route (peer, afi, safi);
2265}
2266
2267struct peer_flag_action
2268{
2269 /* Peer's flag. */
2270 u_int32_t flag;
2271
2272 /* This flag can be set for peer-group member. */
2273 u_char not_for_member;
2274
2275 /* Action when the flag is changed. */
2276 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002277
2278 /* Peer down cause */
2279 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002280};
2281
Stephen Hemminger03621952009-07-21 16:27:20 -07002282static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002283 {
2284 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2285 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2286 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2287 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2288 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002289 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002290 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002291 { 0, 0, 0 }
2292 };
2293
Stephen Hemminger03621952009-07-21 16:27:20 -07002294static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002295 {
2296 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2297 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2298 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2299 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2300 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2301 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2302 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2303 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2304 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2305 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2306 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2307 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2308 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002309 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002310 { 0, 0, 0 }
2311 };
2312
2313/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002314static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002315peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002316 struct peer_flag_action *action, u_int32_t flag)
2317{
2318 int i;
2319 int found = 0;
2320 int reset_in = 0;
2321 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002322 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002323
2324 /* Check peer's frag action. */
2325 for (i = 0; i < size; i++)
2326 {
2327 match = &action_list[i];
2328
2329 if (match->flag == 0)
2330 break;
2331
2332 if (match->flag & flag)
2333 {
2334 found = 1;
2335
2336 if (match->type == peer_change_reset_in)
2337 reset_in = 1;
2338 if (match->type == peer_change_reset_out)
2339 reset_out = 1;
2340 if (match->type == peer_change_reset)
2341 {
2342 reset_in = 1;
2343 reset_out = 1;
2344 }
2345 if (match->not_for_member)
2346 action->not_for_member = 1;
2347 }
2348 }
2349
2350 /* Set peer clear type. */
2351 if (reset_in && reset_out)
2352 action->type = peer_change_reset;
2353 else if (reset_in)
2354 action->type = peer_change_reset_in;
2355 else if (reset_out)
2356 action->type = peer_change_reset_out;
2357 else
2358 action->type = peer_change_none;
2359
2360 return found;
2361}
2362
paul94f2b392005-06-28 12:44:16 +00002363static void
paul718e3742002-12-13 20:15:29 +00002364peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2365{
2366 if (flag == PEER_FLAG_SHUTDOWN)
2367 {
2368 if (CHECK_FLAG (peer->flags, flag))
2369 {
hasso93406d82005-02-02 14:40:33 +00002370 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2371 peer_nsf_stop (peer);
2372
hasso0a486e52005-02-01 20:57:17 +00002373 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2374 if (peer->t_pmax_restart)
2375 {
2376 BGP_TIMER_OFF (peer->t_pmax_restart);
2377 if (BGP_DEBUG (events, EVENTS))
2378 zlog_debug ("%s Maximum-prefix restart timer canceled",
2379 peer->host);
2380 }
2381
hasso93406d82005-02-02 14:40:33 +00002382 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2383 peer_nsf_stop (peer);
2384
paul718e3742002-12-13 20:15:29 +00002385 if (peer->status == Established)
2386 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2387 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2388 else
2389 BGP_EVENT_ADD (peer, BGP_Stop);
2390 }
2391 else
2392 {
2393 peer->v_start = BGP_INIT_START_TIMER;
2394 BGP_EVENT_ADD (peer, BGP_Stop);
2395 }
2396 }
2397 else if (peer->status == Established)
2398 {
hassoc9502432005-02-01 22:01:48 +00002399 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2400 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2401 else if (flag == PEER_FLAG_PASSIVE)
2402 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002403 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002404 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002405
hassoc9502432005-02-01 22:01:48 +00002406 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2407 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002408 }
2409 else
2410 BGP_EVENT_ADD (peer, BGP_Stop);
2411}
2412
2413/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002414static int
paul718e3742002-12-13 20:15:29 +00002415peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2416{
2417 int found;
2418 int size;
2419 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002420 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002421 struct peer_flag_action action;
2422
2423 memset (&action, 0, sizeof (struct peer_flag_action));
2424 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2425
2426 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2427
2428 /* No flag action is found. */
2429 if (! found)
2430 return BGP_ERR_INVALID_FLAG;
2431
2432 /* Not for peer-group member. */
2433 if (action.not_for_member && peer_group_active (peer))
2434 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2435
2436 /* When unset the peer-group member's flag we have to check
2437 peer-group configuration. */
2438 if (! set && peer_group_active (peer))
2439 if (CHECK_FLAG (peer->group->conf->flags, flag))
2440 {
2441 if (flag == PEER_FLAG_SHUTDOWN)
2442 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2443 else
2444 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2445 }
2446
2447 /* Flag conflict check. */
2448 if (set
2449 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2450 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2451 return BGP_ERR_PEER_FLAG_CONFLICT;
2452
2453 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2454 {
2455 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2456 return 0;
2457 if (! set && ! CHECK_FLAG (peer->flags, flag))
2458 return 0;
2459 }
2460
2461 if (set)
2462 SET_FLAG (peer->flags, flag);
2463 else
2464 UNSET_FLAG (peer->flags, flag);
2465
2466 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2467 {
2468 if (action.type == peer_change_reset)
2469 peer_flag_modify_action (peer, flag);
2470
2471 return 0;
2472 }
2473
2474 /* peer-group member updates. */
2475 group = peer->group;
2476
paul1eb8ef22005-04-07 07:30:20 +00002477 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002478 {
2479 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2480 continue;
2481
2482 if (! set && ! CHECK_FLAG (peer->flags, flag))
2483 continue;
2484
2485 if (set)
2486 SET_FLAG (peer->flags, flag);
2487 else
2488 UNSET_FLAG (peer->flags, flag);
2489
2490 if (action.type == peer_change_reset)
2491 peer_flag_modify_action (peer, flag);
2492 }
2493 return 0;
2494}
2495
2496int
2497peer_flag_set (struct peer *peer, u_int32_t flag)
2498{
2499 return peer_flag_modify (peer, flag, 1);
2500}
2501
2502int
2503peer_flag_unset (struct peer *peer, u_int32_t flag)
2504{
2505 return peer_flag_modify (peer, flag, 0);
2506}
2507
paul94f2b392005-06-28 12:44:16 +00002508static int
paul718e3742002-12-13 20:15:29 +00002509peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2510{
2511 if (peer->af_group[afi][safi])
2512 return 1;
2513 return 0;
2514}
2515
paul94f2b392005-06-28 12:44:16 +00002516static int
paul718e3742002-12-13 20:15:29 +00002517peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2518 int set)
2519{
2520 int found;
2521 int size;
paul1eb8ef22005-04-07 07:30:20 +00002522 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002523 struct peer_group *group;
2524 struct peer_flag_action action;
2525
2526 memset (&action, 0, sizeof (struct peer_flag_action));
2527 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2528
2529 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2530
2531 /* No flag action is found. */
2532 if (! found)
2533 return BGP_ERR_INVALID_FLAG;
2534
2535 /* Adress family must be activated. */
2536 if (! peer->afc[afi][safi])
2537 return BGP_ERR_PEER_INACTIVE;
2538
2539 /* Not for peer-group member. */
2540 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2541 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2542
2543 /* Spcecial check for reflector client. */
2544 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2545 && peer_sort (peer) != BGP_PEER_IBGP)
2546 return BGP_ERR_NOT_INTERNAL_PEER;
2547
2548 /* Spcecial check for remove-private-AS. */
2549 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2550 && peer_sort (peer) == BGP_PEER_IBGP)
2551 return BGP_ERR_REMOVE_PRIVATE_AS;
2552
2553 /* When unset the peer-group member's flag we have to check
2554 peer-group configuration. */
2555 if (! set && peer->af_group[afi][safi])
2556 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2557 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2558
2559 /* When current flag configuration is same as requested one. */
2560 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2561 {
2562 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2563 return 0;
2564 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2565 return 0;
2566 }
2567
2568 if (set)
2569 SET_FLAG (peer->af_flags[afi][safi], flag);
2570 else
2571 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2572
2573 /* Execute action when peer is established. */
2574 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2575 && peer->status == Established)
2576 {
2577 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2578 bgp_clear_adj_in (peer, afi, safi);
2579 else
hassoe0701b72004-05-20 09:19:34 +00002580 {
2581 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2582 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2583 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2584 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2585 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2586 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2587 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2588 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2589
2590 peer_change_action (peer, afi, safi, action.type);
2591 }
2592
paul718e3742002-12-13 20:15:29 +00002593 }
2594
2595 /* Peer group member updates. */
2596 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2597 {
2598 group = peer->group;
2599
paul1eb8ef22005-04-07 07:30:20 +00002600 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002601 {
2602 if (! peer->af_group[afi][safi])
2603 continue;
2604
2605 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2606 continue;
2607
2608 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2609 continue;
2610
2611 if (set)
2612 SET_FLAG (peer->af_flags[afi][safi], flag);
2613 else
2614 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2615
2616 if (peer->status == Established)
2617 {
2618 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2619 bgp_clear_adj_in (peer, afi, safi);
2620 else
hassoe0701b72004-05-20 09:19:34 +00002621 {
2622 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2623 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2624 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2625 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2626 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2627 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2628 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2629 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2630
2631 peer_change_action (peer, afi, safi, action.type);
2632 }
paul718e3742002-12-13 20:15:29 +00002633 }
2634 }
2635 }
2636 return 0;
2637}
2638
2639int
2640peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2641{
2642 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2643}
2644
2645int
2646peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2647{
2648 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2649}
2650
2651/* EBGP multihop configuration. */
2652int
2653peer_ebgp_multihop_set (struct peer *peer, int ttl)
2654{
2655 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002656 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002657
2658 if (peer_sort (peer) == BGP_PEER_IBGP)
2659 return 0;
2660
2661 peer->ttl = ttl;
2662
2663 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2664 {
pauleb821182004-05-01 08:44:08 +00002665 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2666 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002667 }
2668 else
2669 {
2670 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002671 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002672 {
2673 if (peer_sort (peer) == BGP_PEER_IBGP)
2674 continue;
paul718e3742002-12-13 20:15:29 +00002675
pauleb821182004-05-01 08:44:08 +00002676 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002677
pauleb821182004-05-01 08:44:08 +00002678 if (peer->fd >= 0)
2679 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2680 }
paul718e3742002-12-13 20:15:29 +00002681 }
2682 return 0;
2683}
2684
2685int
2686peer_ebgp_multihop_unset (struct peer *peer)
2687{
2688 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002689 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002690
2691 if (peer_sort (peer) == BGP_PEER_IBGP)
2692 return 0;
2693
2694 if (peer_group_active (peer))
2695 peer->ttl = peer->group->conf->ttl;
2696 else
2697 peer->ttl = 1;
2698
2699 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2700 {
pauleb821182004-05-01 08:44:08 +00002701 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2702 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002703 }
2704 else
2705 {
2706 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002707 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002708 {
2709 if (peer_sort (peer) == BGP_PEER_IBGP)
2710 continue;
paul718e3742002-12-13 20:15:29 +00002711
pauleb821182004-05-01 08:44:08 +00002712 peer->ttl = 1;
2713
2714 if (peer->fd >= 0)
2715 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2716 }
paul718e3742002-12-13 20:15:29 +00002717 }
2718 return 0;
2719}
2720
2721/* Neighbor description. */
2722int
2723peer_description_set (struct peer *peer, char *desc)
2724{
2725 if (peer->desc)
2726 XFREE (MTYPE_PEER_DESC, peer->desc);
2727
2728 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2729
2730 return 0;
2731}
2732
2733int
2734peer_description_unset (struct peer *peer)
2735{
2736 if (peer->desc)
2737 XFREE (MTYPE_PEER_DESC, peer->desc);
2738
2739 peer->desc = NULL;
2740
2741 return 0;
2742}
2743
2744/* Neighbor update-source. */
2745int
paulfd79ac92004-10-13 05:06:08 +00002746peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002747{
2748 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002749 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002750
2751 if (peer->update_if)
2752 {
2753 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2754 && strcmp (peer->update_if, ifname) == 0)
2755 return 0;
2756
2757 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2758 peer->update_if = NULL;
2759 }
2760
2761 if (peer->update_source)
2762 {
2763 sockunion_free (peer->update_source);
2764 peer->update_source = NULL;
2765 }
2766
2767 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2768
2769 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2770 {
2771 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002772 {
2773 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2774 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2775 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2776 }
paul718e3742002-12-13 20:15:29 +00002777 else
2778 BGP_EVENT_ADD (peer, BGP_Stop);
2779 return 0;
2780 }
2781
2782 /* peer-group member updates. */
2783 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002784 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002785 {
2786 if (peer->update_if)
2787 {
2788 if (strcmp (peer->update_if, ifname) == 0)
2789 continue;
2790
2791 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2792 peer->update_if = NULL;
2793 }
2794
2795 if (peer->update_source)
2796 {
2797 sockunion_free (peer->update_source);
2798 peer->update_source = NULL;
2799 }
2800
2801 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2802
2803 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002804 {
2805 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2806 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2807 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2808 }
paul718e3742002-12-13 20:15:29 +00002809 else
2810 BGP_EVENT_ADD (peer, BGP_Stop);
2811 }
2812 return 0;
2813}
2814
2815int
2816peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2817{
2818 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002819 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002820
2821 if (peer->update_source)
2822 {
2823 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2824 && sockunion_cmp (peer->update_source, su) == 0)
2825 return 0;
2826 sockunion_free (peer->update_source);
2827 peer->update_source = NULL;
2828 }
2829
2830 if (peer->update_if)
2831 {
2832 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2833 peer->update_if = NULL;
2834 }
2835
2836 peer->update_source = sockunion_dup (su);
2837
2838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
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 return 0;
2849 }
2850
2851 /* peer-group member updates. */
2852 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002853 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002854 {
2855 if (peer->update_source)
2856 {
2857 if (sockunion_cmp (peer->update_source, su) == 0)
2858 continue;
2859 sockunion_free (peer->update_source);
2860 peer->update_source = NULL;
2861 }
2862
2863 if (peer->update_if)
2864 {
2865 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2866 peer->update_if = NULL;
2867 }
2868
2869 peer->update_source = sockunion_dup (su);
2870
2871 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002872 {
2873 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2874 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2875 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2876 }
paul718e3742002-12-13 20:15:29 +00002877 else
2878 BGP_EVENT_ADD (peer, BGP_Stop);
2879 }
2880 return 0;
2881}
2882
2883int
2884peer_update_source_unset (struct peer *peer)
2885{
2886 union sockunion *su;
2887 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002888 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002889
2890 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2891 && ! peer->update_source
2892 && ! peer->update_if)
2893 return 0;
2894
2895 if (peer->update_source)
2896 {
2897 sockunion_free (peer->update_source);
2898 peer->update_source = NULL;
2899 }
2900 if (peer->update_if)
2901 {
2902 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2903 peer->update_if = NULL;
2904 }
2905
2906 if (peer_group_active (peer))
2907 {
2908 group = peer->group;
2909
2910 if (group->conf->update_source)
2911 {
2912 su = sockunion_dup (group->conf->update_source);
2913 peer->update_source = su;
2914 }
2915 else if (group->conf->update_if)
2916 peer->update_if =
2917 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2918 }
2919
2920 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2921 {
2922 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002923 {
2924 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2925 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2926 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2927 }
paul718e3742002-12-13 20:15:29 +00002928 else
2929 BGP_EVENT_ADD (peer, BGP_Stop);
2930 return 0;
2931 }
2932
2933 /* peer-group member updates. */
2934 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002935 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002936 {
2937 if (! peer->update_source && ! peer->update_if)
2938 continue;
2939
2940 if (peer->update_source)
2941 {
2942 sockunion_free (peer->update_source);
2943 peer->update_source = NULL;
2944 }
2945
2946 if (peer->update_if)
2947 {
2948 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2949 peer->update_if = NULL;
2950 }
2951
2952 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002953 {
2954 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2955 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2956 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2957 }
paul718e3742002-12-13 20:15:29 +00002958 else
2959 BGP_EVENT_ADD (peer, BGP_Stop);
2960 }
2961 return 0;
2962}
2963
2964int
2965peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002966 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002967{
2968 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002969 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002970
2971 /* Adress family must be activated. */
2972 if (! peer->afc[afi][safi])
2973 return BGP_ERR_PEER_INACTIVE;
2974
2975 /* Default originate can't be used for peer group memeber. */
2976 if (peer_is_group_member (peer, afi, safi))
2977 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2978
2979 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2980 || (rmap && ! peer->default_rmap[afi][safi].name)
2981 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2982 {
2983 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2984
2985 if (rmap)
2986 {
2987 if (peer->default_rmap[afi][safi].name)
2988 free (peer->default_rmap[afi][safi].name);
2989 peer->default_rmap[afi][safi].name = strdup (rmap);
2990 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2991 }
2992 }
2993
2994 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2995 {
2996 if (peer->status == Established && peer->afc_nego[afi][safi])
2997 bgp_default_originate (peer, afi, safi, 0);
2998 return 0;
2999 }
3000
3001 /* peer-group member updates. */
3002 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003003 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003004 {
3005 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3006
3007 if (rmap)
3008 {
3009 if (peer->default_rmap[afi][safi].name)
3010 free (peer->default_rmap[afi][safi].name);
3011 peer->default_rmap[afi][safi].name = strdup (rmap);
3012 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3013 }
3014
3015 if (peer->status == Established && peer->afc_nego[afi][safi])
3016 bgp_default_originate (peer, afi, safi, 0);
3017 }
3018 return 0;
3019}
3020
3021int
3022peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3023{
3024 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003025 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003026
3027 /* Adress family must be activated. */
3028 if (! peer->afc[afi][safi])
3029 return BGP_ERR_PEER_INACTIVE;
3030
3031 /* Default originate can't be used for peer group memeber. */
3032 if (peer_is_group_member (peer, afi, safi))
3033 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3034
3035 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3036 {
3037 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3038
3039 if (peer->default_rmap[afi][safi].name)
3040 free (peer->default_rmap[afi][safi].name);
3041 peer->default_rmap[afi][safi].name = NULL;
3042 peer->default_rmap[afi][safi].map = NULL;
3043 }
3044
3045 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3046 {
3047 if (peer->status == Established && peer->afc_nego[afi][safi])
3048 bgp_default_originate (peer, afi, safi, 1);
3049 return 0;
3050 }
3051
3052 /* peer-group member updates. */
3053 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003054 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003055 {
3056 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3057
3058 if (peer->default_rmap[afi][safi].name)
3059 free (peer->default_rmap[afi][safi].name);
3060 peer->default_rmap[afi][safi].name = NULL;
3061 peer->default_rmap[afi][safi].map = NULL;
3062
3063 if (peer->status == Established && peer->afc_nego[afi][safi])
3064 bgp_default_originate (peer, afi, safi, 1);
3065 }
3066 return 0;
3067}
3068
3069int
3070peer_port_set (struct peer *peer, u_int16_t port)
3071{
3072 peer->port = port;
3073 return 0;
3074}
3075
3076int
3077peer_port_unset (struct peer *peer)
3078{
3079 peer->port = BGP_PORT_DEFAULT;
3080 return 0;
3081}
3082
3083/* neighbor weight. */
3084int
3085peer_weight_set (struct peer *peer, u_int16_t weight)
3086{
3087 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003088 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003089
3090 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3091 peer->weight = weight;
3092
3093 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3094 return 0;
3095
3096 /* peer-group member updates. */
3097 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003098 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003099 {
3100 peer->weight = group->conf->weight;
3101 }
3102 return 0;
3103}
3104
3105int
3106peer_weight_unset (struct peer *peer)
3107{
3108 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003109 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003110
3111 /* Set default weight. */
3112 if (peer_group_active (peer))
3113 peer->weight = peer->group->conf->weight;
3114 else
3115 peer->weight = 0;
3116
3117 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3118
3119 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3120 return 0;
3121
3122 /* peer-group member updates. */
3123 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003124 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003125 {
3126 peer->weight = 0;
3127 }
3128 return 0;
3129}
3130
3131int
3132peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3133{
3134 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003135 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003136
3137 /* Not for peer group memeber. */
3138 if (peer_group_active (peer))
3139 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3140
3141 /* keepalive value check. */
3142 if (keepalive > 65535)
3143 return BGP_ERR_INVALID_VALUE;
3144
3145 /* Holdtime value check. */
3146 if (holdtime > 65535)
3147 return BGP_ERR_INVALID_VALUE;
3148
3149 /* Holdtime value must be either 0 or greater than 3. */
3150 if (holdtime < 3 && holdtime != 0)
3151 return BGP_ERR_INVALID_VALUE;
3152
3153 /* Set value to the configuration. */
3154 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3155 peer->holdtime = holdtime;
3156 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3157
3158 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3159 return 0;
3160
3161 /* peer-group member updates. */
3162 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003163 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003164 {
3165 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3166 peer->holdtime = group->conf->holdtime;
3167 peer->keepalive = group->conf->keepalive;
3168 }
3169 return 0;
3170}
3171
3172int
3173peer_timers_unset (struct peer *peer)
3174{
3175 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003176 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003177
3178 if (peer_group_active (peer))
3179 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3180
3181 /* Clear configuration. */
3182 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3183 peer->keepalive = 0;
3184 peer->holdtime = 0;
3185
3186 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3187 return 0;
3188
3189 /* peer-group member updates. */
3190 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003191 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003192 {
3193 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3194 peer->holdtime = 0;
3195 peer->keepalive = 0;
3196 }
3197
3198 return 0;
3199}
3200
3201int
3202peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3203{
3204 if (peer_group_active (peer))
3205 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3206
3207 if (connect > 65535)
3208 return BGP_ERR_INVALID_VALUE;
3209
3210 /* Set value to the configuration. */
3211 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3212 peer->connect = connect;
3213
3214 /* Set value to timer setting. */
3215 peer->v_connect = connect;
3216
3217 return 0;
3218}
3219
3220int
3221peer_timers_connect_unset (struct peer *peer)
3222{
3223 if (peer_group_active (peer))
3224 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3225
3226 /* Clear configuration. */
3227 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3228 peer->connect = 0;
3229
3230 /* Set timer setting to default value. */
3231 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3232
3233 return 0;
3234}
3235
3236int
3237peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3238{
3239 if (peer_group_active (peer))
3240 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3241
3242 if (routeadv > 600)
3243 return BGP_ERR_INVALID_VALUE;
3244
3245 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3246 peer->routeadv = routeadv;
3247 peer->v_routeadv = routeadv;
3248
3249 return 0;
3250}
3251
3252int
3253peer_advertise_interval_unset (struct peer *peer)
3254{
3255 if (peer_group_active (peer))
3256 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3257
3258 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3259 peer->routeadv = 0;
3260
3261 if (peer_sort (peer) == BGP_PEER_IBGP)
3262 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3263 else
3264 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3265
3266 return 0;
3267}
3268
paul718e3742002-12-13 20:15:29 +00003269/* neighbor interface */
3270int
paulfd79ac92004-10-13 05:06:08 +00003271peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003272{
3273 if (peer->ifname)
3274 free (peer->ifname);
3275 peer->ifname = strdup (str);
3276
3277 return 0;
3278}
3279
3280int
3281peer_interface_unset (struct peer *peer)
3282{
3283 if (peer->ifname)
3284 free (peer->ifname);
3285 peer->ifname = NULL;
3286
3287 return 0;
3288}
3289
3290/* Allow-as in. */
3291int
3292peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3293{
3294 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003295 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003296
3297 if (allow_num < 1 || allow_num > 10)
3298 return BGP_ERR_INVALID_VALUE;
3299
3300 if (peer->allowas_in[afi][safi] != allow_num)
3301 {
3302 peer->allowas_in[afi][safi] = allow_num;
3303 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3304 peer_change_action (peer, afi, safi, peer_change_reset_in);
3305 }
3306
3307 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3308 return 0;
3309
3310 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003311 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003312 {
3313 if (peer->allowas_in[afi][safi] != allow_num)
3314 {
3315 peer->allowas_in[afi][safi] = allow_num;
3316 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3317 peer_change_action (peer, afi, safi, peer_change_reset_in);
3318 }
3319
3320 }
3321 return 0;
3322}
3323
3324int
3325peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3326{
3327 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003328 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003329
3330 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3331 {
3332 peer->allowas_in[afi][safi] = 0;
3333 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3334 }
3335
3336 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3337 return 0;
3338
3339 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003340 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003341 {
3342 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3343 {
3344 peer->allowas_in[afi][safi] = 0;
3345 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3346 }
3347 }
3348 return 0;
3349}
3350
3351int
3352peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3353{
3354 struct bgp *bgp = peer->bgp;
3355 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003356 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003357
3358 if (peer_sort (peer) != BGP_PEER_EBGP
3359 && peer_sort (peer) != BGP_PEER_INTERNAL)
3360 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3361
3362 if (bgp->as == as)
3363 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3364
3365 if (peer_group_active (peer))
3366 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3367
3368 if (peer->change_local_as == as &&
3369 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3370 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3371 return 0;
3372
3373 peer->change_local_as = as;
3374 if (no_prepend)
3375 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3376 else
3377 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3378
3379 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3380 {
3381 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003382 {
3383 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3384 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3385 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3386 }
paul718e3742002-12-13 20:15:29 +00003387 else
3388 BGP_EVENT_ADD (peer, BGP_Stop);
3389
3390 return 0;
3391 }
3392
3393 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003394 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003395 {
3396 peer->change_local_as = as;
3397 if (no_prepend)
3398 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3399 else
3400 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3401
3402 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003403 {
3404 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3405 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3406 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3407 }
paul718e3742002-12-13 20:15:29 +00003408 else
3409 BGP_EVENT_ADD (peer, BGP_Stop);
3410 }
3411
3412 return 0;
3413}
3414
3415int
3416peer_local_as_unset (struct peer *peer)
3417{
3418 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003419 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003420
3421 if (peer_group_active (peer))
3422 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3423
3424 if (! peer->change_local_as)
3425 return 0;
3426
3427 peer->change_local_as = 0;
3428 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3429
3430 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3431 {
3432 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003433 {
3434 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3435 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3436 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3437 }
paul718e3742002-12-13 20:15:29 +00003438 else
3439 BGP_EVENT_ADD (peer, BGP_Stop);
3440
3441 return 0;
3442 }
3443
3444 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003445 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003446 {
3447 peer->change_local_as = 0;
3448 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3449
3450 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003451 {
3452 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3453 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3454 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3455 }
paul718e3742002-12-13 20:15:29 +00003456 else
3457 BGP_EVENT_ADD (peer, BGP_Stop);
3458 }
3459 return 0;
3460}
3461
Paul Jakma0df7c912008-07-21 21:02:49 +00003462/* Set password for authenticating with the peer. */
3463int
3464peer_password_set (struct peer *peer, const char *password)
3465{
3466 struct listnode *nn, *nnode;
3467 int len = password ? strlen(password) : 0;
3468 int ret = BGP_SUCCESS;
3469
3470 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3471 return BGP_ERR_INVALID_VALUE;
3472
3473 if (peer->password && strcmp (peer->password, password) == 0
3474 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3475 return 0;
3476
3477 if (peer->password)
3478 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3479
3480 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3481
3482 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3483 {
3484 if (peer->status == Established)
3485 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3486 else
3487 BGP_EVENT_ADD (peer, BGP_Stop);
3488
3489 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3490 }
3491
3492 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3493 {
3494 if (peer->password && strcmp (peer->password, password) == 0)
3495 continue;
3496
3497 if (peer->password)
3498 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3499
3500 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3501
3502 if (peer->status == Established)
3503 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3504 else
3505 BGP_EVENT_ADD (peer, BGP_Stop);
3506
3507 if (bgp_md5_set (peer) < 0)
3508 ret = BGP_ERR_TCPSIG_FAILED;
3509 }
3510
3511 return ret;
3512}
3513
3514int
3515peer_password_unset (struct peer *peer)
3516{
3517 struct listnode *nn, *nnode;
3518
3519 if (!peer->password
3520 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3521 return 0;
3522
3523 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3524 {
3525 if (peer_group_active (peer)
3526 && peer->group->conf->password
3527 && strcmp (peer->group->conf->password, peer->password) == 0)
3528 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3529
3530 if (peer->status == Established)
3531 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3532 else
3533 BGP_EVENT_ADD (peer, BGP_Stop);
3534
3535 if (peer->password)
3536 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3537
3538 peer->password = NULL;
3539
3540 bgp_md5_set (peer);
3541
3542 return 0;
3543 }
3544
3545 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3546 peer->password = NULL;
3547
3548 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3549 {
3550 if (!peer->password)
3551 continue;
3552
3553 if (peer->status == Established)
3554 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3555 else
3556 BGP_EVENT_ADD (peer, BGP_Stop);
3557
3558 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3559 peer->password = NULL;
3560
3561 bgp_md5_set (peer);
3562 }
3563
3564 return 0;
3565}
3566
paul718e3742002-12-13 20:15:29 +00003567/* Set distribute list to the peer. */
3568int
3569peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003570 const char *name)
paul718e3742002-12-13 20:15:29 +00003571{
3572 struct bgp_filter *filter;
3573 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003574 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003575
3576 if (! peer->afc[afi][safi])
3577 return BGP_ERR_PEER_INACTIVE;
3578
3579 if (direct != FILTER_IN && direct != FILTER_OUT)
3580 return BGP_ERR_INVALID_VALUE;
3581
3582 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3583 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3584
3585 filter = &peer->filter[afi][safi];
3586
3587 if (filter->plist[direct].name)
3588 return BGP_ERR_PEER_FILTER_CONFLICT;
3589
3590 if (filter->dlist[direct].name)
3591 free (filter->dlist[direct].name);
3592 filter->dlist[direct].name = strdup (name);
3593 filter->dlist[direct].alist = access_list_lookup (afi, name);
3594
3595 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3596 return 0;
3597
3598 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003599 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003600 {
3601 filter = &peer->filter[afi][safi];
3602
3603 if (! peer->af_group[afi][safi])
3604 continue;
3605
3606 if (filter->dlist[direct].name)
3607 free (filter->dlist[direct].name);
3608 filter->dlist[direct].name = strdup (name);
3609 filter->dlist[direct].alist = access_list_lookup (afi, name);
3610 }
3611
3612 return 0;
3613}
3614
3615int
3616peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3617{
3618 struct bgp_filter *filter;
3619 struct bgp_filter *gfilter;
3620 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003621 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003622
3623 if (! peer->afc[afi][safi])
3624 return BGP_ERR_PEER_INACTIVE;
3625
3626 if (direct != FILTER_IN && direct != FILTER_OUT)
3627 return BGP_ERR_INVALID_VALUE;
3628
3629 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3630 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3631
3632 filter = &peer->filter[afi][safi];
3633
3634 /* apply peer-group filter */
3635 if (peer->af_group[afi][safi])
3636 {
3637 gfilter = &peer->group->conf->filter[afi][safi];
3638
3639 if (gfilter->dlist[direct].name)
3640 {
3641 if (filter->dlist[direct].name)
3642 free (filter->dlist[direct].name);
3643 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3644 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3645 return 0;
3646 }
3647 }
3648
3649 if (filter->dlist[direct].name)
3650 free (filter->dlist[direct].name);
3651 filter->dlist[direct].name = NULL;
3652 filter->dlist[direct].alist = NULL;
3653
3654 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3655 return 0;
3656
3657 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003658 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003659 {
3660 filter = &peer->filter[afi][safi];
3661
3662 if (! peer->af_group[afi][safi])
3663 continue;
3664
3665 if (filter->dlist[direct].name)
3666 free (filter->dlist[direct].name);
3667 filter->dlist[direct].name = NULL;
3668 filter->dlist[direct].alist = NULL;
3669 }
3670
3671 return 0;
3672}
3673
3674/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003675static void
paul718e3742002-12-13 20:15:29 +00003676peer_distribute_update (struct access_list *access)
3677{
3678 afi_t afi;
3679 safi_t safi;
3680 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003681 struct listnode *mnode, *mnnode;
3682 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003683 struct bgp *bgp;
3684 struct peer *peer;
3685 struct peer_group *group;
3686 struct bgp_filter *filter;
3687
paul1eb8ef22005-04-07 07:30:20 +00003688 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003689 {
paul1eb8ef22005-04-07 07:30:20 +00003690 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003691 {
3692 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3693 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3694 {
3695 filter = &peer->filter[afi][safi];
3696
3697 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3698 {
3699 if (filter->dlist[direct].name)
3700 filter->dlist[direct].alist =
3701 access_list_lookup (afi, filter->dlist[direct].name);
3702 else
3703 filter->dlist[direct].alist = NULL;
3704 }
3705 }
3706 }
paul1eb8ef22005-04-07 07:30:20 +00003707 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003708 {
3709 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3710 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3711 {
3712 filter = &group->conf->filter[afi][safi];
3713
3714 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3715 {
3716 if (filter->dlist[direct].name)
3717 filter->dlist[direct].alist =
3718 access_list_lookup (afi, filter->dlist[direct].name);
3719 else
3720 filter->dlist[direct].alist = NULL;
3721 }
3722 }
3723 }
3724 }
3725}
3726
3727/* Set prefix list to the peer. */
3728int
3729peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003730 const char *name)
paul718e3742002-12-13 20:15:29 +00003731{
3732 struct bgp_filter *filter;
3733 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003734 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003735
3736 if (! peer->afc[afi][safi])
3737 return BGP_ERR_PEER_INACTIVE;
3738
3739 if (direct != FILTER_IN && direct != FILTER_OUT)
3740 return BGP_ERR_INVALID_VALUE;
3741
3742 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3743 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3744
3745 filter = &peer->filter[afi][safi];
3746
3747 if (filter->dlist[direct].name)
3748 return BGP_ERR_PEER_FILTER_CONFLICT;
3749
3750 if (filter->plist[direct].name)
3751 free (filter->plist[direct].name);
3752 filter->plist[direct].name = strdup (name);
3753 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3754
3755 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3756 return 0;
3757
3758 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003759 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003760 {
3761 filter = &peer->filter[afi][safi];
3762
3763 if (! peer->af_group[afi][safi])
3764 continue;
3765
3766 if (filter->plist[direct].name)
3767 free (filter->plist[direct].name);
3768 filter->plist[direct].name = strdup (name);
3769 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3770 }
3771 return 0;
3772}
3773
3774int
3775peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3776{
3777 struct bgp_filter *filter;
3778 struct bgp_filter *gfilter;
3779 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003780 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003781
3782 if (! peer->afc[afi][safi])
3783 return BGP_ERR_PEER_INACTIVE;
3784
3785 if (direct != FILTER_IN && direct != FILTER_OUT)
3786 return BGP_ERR_INVALID_VALUE;
3787
3788 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3789 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3790
3791 filter = &peer->filter[afi][safi];
3792
3793 /* apply peer-group filter */
3794 if (peer->af_group[afi][safi])
3795 {
3796 gfilter = &peer->group->conf->filter[afi][safi];
3797
3798 if (gfilter->plist[direct].name)
3799 {
3800 if (filter->plist[direct].name)
3801 free (filter->plist[direct].name);
3802 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3803 filter->plist[direct].plist = gfilter->plist[direct].plist;
3804 return 0;
3805 }
3806 }
3807
3808 if (filter->plist[direct].name)
3809 free (filter->plist[direct].name);
3810 filter->plist[direct].name = NULL;
3811 filter->plist[direct].plist = NULL;
3812
3813 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3814 return 0;
3815
3816 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003817 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003818 {
3819 filter = &peer->filter[afi][safi];
3820
3821 if (! peer->af_group[afi][safi])
3822 continue;
3823
3824 if (filter->plist[direct].name)
3825 free (filter->plist[direct].name);
3826 filter->plist[direct].name = NULL;
3827 filter->plist[direct].plist = NULL;
3828 }
3829
3830 return 0;
3831}
3832
3833/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003834static void
paul718e3742002-12-13 20:15:29 +00003835peer_prefix_list_update (struct prefix_list *plist)
3836{
paul1eb8ef22005-04-07 07:30:20 +00003837 struct listnode *mnode, *mnnode;
3838 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003839 struct bgp *bgp;
3840 struct peer *peer;
3841 struct peer_group *group;
3842 struct bgp_filter *filter;
3843 afi_t afi;
3844 safi_t safi;
3845 int direct;
3846
paul1eb8ef22005-04-07 07:30:20 +00003847 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003848 {
paul1eb8ef22005-04-07 07:30:20 +00003849 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003850 {
3851 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3852 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3853 {
3854 filter = &peer->filter[afi][safi];
3855
3856 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3857 {
3858 if (filter->plist[direct].name)
3859 filter->plist[direct].plist =
3860 prefix_list_lookup (afi, filter->plist[direct].name);
3861 else
3862 filter->plist[direct].plist = NULL;
3863 }
3864 }
3865 }
paul1eb8ef22005-04-07 07:30:20 +00003866 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003867 {
3868 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3869 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3870 {
3871 filter = &group->conf->filter[afi][safi];
3872
3873 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3874 {
3875 if (filter->plist[direct].name)
3876 filter->plist[direct].plist =
3877 prefix_list_lookup (afi, filter->plist[direct].name);
3878 else
3879 filter->plist[direct].plist = NULL;
3880 }
3881 }
3882 }
3883 }
3884}
3885
3886int
3887peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003888 const char *name)
paul718e3742002-12-13 20:15:29 +00003889{
3890 struct bgp_filter *filter;
3891 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003892 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003893
3894 if (! peer->afc[afi][safi])
3895 return BGP_ERR_PEER_INACTIVE;
3896
3897 if (direct != FILTER_IN && direct != FILTER_OUT)
3898 return BGP_ERR_INVALID_VALUE;
3899
3900 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3901 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3902
3903 filter = &peer->filter[afi][safi];
3904
3905 if (filter->aslist[direct].name)
3906 free (filter->aslist[direct].name);
3907 filter->aslist[direct].name = strdup (name);
3908 filter->aslist[direct].aslist = as_list_lookup (name);
3909
3910 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3911 return 0;
3912
3913 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003914 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003915 {
3916 filter = &peer->filter[afi][safi];
3917
3918 if (! peer->af_group[afi][safi])
3919 continue;
3920
3921 if (filter->aslist[direct].name)
3922 free (filter->aslist[direct].name);
3923 filter->aslist[direct].name = strdup (name);
3924 filter->aslist[direct].aslist = as_list_lookup (name);
3925 }
3926 return 0;
3927}
3928
3929int
3930peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3931{
3932 struct bgp_filter *filter;
3933 struct bgp_filter *gfilter;
3934 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003935 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003936
3937 if (! peer->afc[afi][safi])
3938 return BGP_ERR_PEER_INACTIVE;
3939
hassob5f29602005-05-25 21:00:28 +00003940 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003941 return BGP_ERR_INVALID_VALUE;
3942
hassob5f29602005-05-25 21:00:28 +00003943 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003944 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3945
3946 filter = &peer->filter[afi][safi];
3947
3948 /* apply peer-group filter */
3949 if (peer->af_group[afi][safi])
3950 {
3951 gfilter = &peer->group->conf->filter[afi][safi];
3952
3953 if (gfilter->aslist[direct].name)
3954 {
3955 if (filter->aslist[direct].name)
3956 free (filter->aslist[direct].name);
3957 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3958 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3959 return 0;
3960 }
3961 }
3962
3963 if (filter->aslist[direct].name)
3964 free (filter->aslist[direct].name);
3965 filter->aslist[direct].name = NULL;
3966 filter->aslist[direct].aslist = NULL;
3967
3968 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3969 return 0;
3970
3971 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003972 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003973 {
3974 filter = &peer->filter[afi][safi];
3975
3976 if (! peer->af_group[afi][safi])
3977 continue;
3978
3979 if (filter->aslist[direct].name)
3980 free (filter->aslist[direct].name);
3981 filter->aslist[direct].name = NULL;
3982 filter->aslist[direct].aslist = NULL;
3983 }
3984
3985 return 0;
3986}
3987
paul94f2b392005-06-28 12:44:16 +00003988static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003989peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003990{
3991 afi_t afi;
3992 safi_t safi;
3993 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003994 struct listnode *mnode, *mnnode;
3995 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003996 struct bgp *bgp;
3997 struct peer *peer;
3998 struct peer_group *group;
3999 struct bgp_filter *filter;
4000
paul1eb8ef22005-04-07 07:30:20 +00004001 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004002 {
paul1eb8ef22005-04-07 07:30:20 +00004003 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004004 {
4005 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4006 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4007 {
4008 filter = &peer->filter[afi][safi];
4009
4010 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4011 {
4012 if (filter->aslist[direct].name)
4013 filter->aslist[direct].aslist =
4014 as_list_lookup (filter->aslist[direct].name);
4015 else
4016 filter->aslist[direct].aslist = NULL;
4017 }
4018 }
4019 }
paul1eb8ef22005-04-07 07:30:20 +00004020 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004021 {
4022 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4023 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4024 {
4025 filter = &group->conf->filter[afi][safi];
4026
4027 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4028 {
4029 if (filter->aslist[direct].name)
4030 filter->aslist[direct].aslist =
4031 as_list_lookup (filter->aslist[direct].name);
4032 else
4033 filter->aslist[direct].aslist = NULL;
4034 }
4035 }
4036 }
4037 }
4038}
4039
4040/* Set route-map to the peer. */
4041int
4042peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004043 const char *name)
paul718e3742002-12-13 20:15:29 +00004044{
4045 struct bgp_filter *filter;
4046 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004047 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004048
4049 if (! peer->afc[afi][safi])
4050 return BGP_ERR_PEER_INACTIVE;
4051
paulfee0f4c2004-09-13 05:12:46 +00004052 if (direct != RMAP_IN && direct != RMAP_OUT &&
4053 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004054 return BGP_ERR_INVALID_VALUE;
4055
paulfee0f4c2004-09-13 05:12:46 +00004056 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4057 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004058 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4059
4060 filter = &peer->filter[afi][safi];
4061
4062 if (filter->map[direct].name)
4063 free (filter->map[direct].name);
4064
4065 filter->map[direct].name = strdup (name);
4066 filter->map[direct].map = route_map_lookup_by_name (name);
4067
4068 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4069 return 0;
4070
4071 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004072 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004073 {
4074 filter = &peer->filter[afi][safi];
4075
4076 if (! peer->af_group[afi][safi])
4077 continue;
4078
4079 if (filter->map[direct].name)
4080 free (filter->map[direct].name);
4081 filter->map[direct].name = strdup (name);
4082 filter->map[direct].map = route_map_lookup_by_name (name);
4083 }
4084 return 0;
4085}
4086
4087/* Unset route-map from the peer. */
4088int
4089peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4090{
4091 struct bgp_filter *filter;
4092 struct bgp_filter *gfilter;
4093 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004094 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004095
4096 if (! peer->afc[afi][safi])
4097 return BGP_ERR_PEER_INACTIVE;
4098
hassob5f29602005-05-25 21:00:28 +00004099 if (direct != RMAP_IN && direct != RMAP_OUT &&
4100 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004101 return BGP_ERR_INVALID_VALUE;
4102
hassob5f29602005-05-25 21:00:28 +00004103 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4104 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004105 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4106
4107 filter = &peer->filter[afi][safi];
4108
4109 /* apply peer-group filter */
4110 if (peer->af_group[afi][safi])
4111 {
4112 gfilter = &peer->group->conf->filter[afi][safi];
4113
4114 if (gfilter->map[direct].name)
4115 {
4116 if (filter->map[direct].name)
4117 free (filter->map[direct].name);
4118 filter->map[direct].name = strdup (gfilter->map[direct].name);
4119 filter->map[direct].map = gfilter->map[direct].map;
4120 return 0;
4121 }
4122 }
4123
4124 if (filter->map[direct].name)
4125 free (filter->map[direct].name);
4126 filter->map[direct].name = NULL;
4127 filter->map[direct].map = NULL;
4128
4129 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4130 return 0;
4131
4132 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004133 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004134 {
4135 filter = &peer->filter[afi][safi];
4136
4137 if (! peer->af_group[afi][safi])
4138 continue;
4139
4140 if (filter->map[direct].name)
4141 free (filter->map[direct].name);
4142 filter->map[direct].name = NULL;
4143 filter->map[direct].map = NULL;
4144 }
4145 return 0;
4146}
4147
4148/* Set unsuppress-map to the peer. */
4149int
paulfd79ac92004-10-13 05:06:08 +00004150peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4151 const char *name)
paul718e3742002-12-13 20:15:29 +00004152{
4153 struct bgp_filter *filter;
4154 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004156
4157 if (! peer->afc[afi][safi])
4158 return BGP_ERR_PEER_INACTIVE;
4159
4160 if (peer_is_group_member (peer, afi, safi))
4161 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4162
4163 filter = &peer->filter[afi][safi];
4164
4165 if (filter->usmap.name)
4166 free (filter->usmap.name);
4167
4168 filter->usmap.name = strdup (name);
4169 filter->usmap.map = route_map_lookup_by_name (name);
4170
4171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4172 return 0;
4173
4174 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004175 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004176 {
4177 filter = &peer->filter[afi][safi];
4178
4179 if (! peer->af_group[afi][safi])
4180 continue;
4181
4182 if (filter->usmap.name)
4183 free (filter->usmap.name);
4184 filter->usmap.name = strdup (name);
4185 filter->usmap.map = route_map_lookup_by_name (name);
4186 }
4187 return 0;
4188}
4189
4190/* Unset route-map from the peer. */
4191int
4192peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4193{
4194 struct bgp_filter *filter;
4195 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004196 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004197
4198 if (! peer->afc[afi][safi])
4199 return BGP_ERR_PEER_INACTIVE;
4200
4201 if (peer_is_group_member (peer, afi, safi))
4202 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4203
4204 filter = &peer->filter[afi][safi];
4205
4206 if (filter->usmap.name)
4207 free (filter->usmap.name);
4208 filter->usmap.name = NULL;
4209 filter->usmap.map = NULL;
4210
4211 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4212 return 0;
4213
4214 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004215 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004216 {
4217 filter = &peer->filter[afi][safi];
4218
4219 if (! peer->af_group[afi][safi])
4220 continue;
4221
4222 if (filter->usmap.name)
4223 free (filter->usmap.name);
4224 filter->usmap.name = NULL;
4225 filter->usmap.map = NULL;
4226 }
4227 return 0;
4228}
4229
4230int
4231peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004232 u_int32_t max, u_char threshold,
4233 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004234{
4235 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004236 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004237
4238 if (! peer->afc[afi][safi])
4239 return BGP_ERR_PEER_INACTIVE;
4240
4241 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4242 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004243 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004244 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004245 if (warning)
4246 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4247 else
4248 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4249
4250 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4251 return 0;
4252
4253 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004254 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004255 {
4256 if (! peer->af_group[afi][safi])
4257 continue;
4258
4259 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4260 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004261 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004262 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004263 if (warning)
4264 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4265 else
4266 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4267 }
4268 return 0;
4269}
4270
4271int
4272peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4273{
4274 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004275 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004276
4277 if (! peer->afc[afi][safi])
4278 return BGP_ERR_PEER_INACTIVE;
4279
4280 /* apply peer-group config */
4281 if (peer->af_group[afi][safi])
4282 {
4283 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4284 PEER_FLAG_MAX_PREFIX))
4285 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4286 else
4287 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4288
4289 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4290 PEER_FLAG_MAX_PREFIX_WARNING))
4291 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4292 else
4293 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4294
4295 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004296 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004297 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004298 return 0;
4299 }
4300
4301 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4302 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4303 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004304 peer->pmax_threshold[afi][safi] = 0;
4305 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004306
4307 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4308 return 0;
4309
4310 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004311 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004312 {
4313 if (! peer->af_group[afi][safi])
4314 continue;
4315
4316 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4317 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4318 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004319 peer->pmax_threshold[afi][safi] = 0;
4320 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004321 }
4322 return 0;
4323}
4324
4325int
4326peer_clear (struct peer *peer)
4327{
4328 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4329 {
hasso0a486e52005-02-01 20:57:17 +00004330 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4331 {
4332 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4333 if (peer->t_pmax_restart)
4334 {
4335 BGP_TIMER_OFF (peer->t_pmax_restart);
4336 if (BGP_DEBUG (events, EVENTS))
4337 zlog_debug ("%s Maximum-prefix restart timer canceled",
4338 peer->host);
4339 }
4340 BGP_EVENT_ADD (peer, BGP_Start);
4341 return 0;
4342 }
4343
paul718e3742002-12-13 20:15:29 +00004344 peer->v_start = BGP_INIT_START_TIMER;
4345 if (peer->status == Established)
4346 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4347 BGP_NOTIFY_CEASE_ADMIN_RESET);
4348 else
4349 BGP_EVENT_ADD (peer, BGP_Stop);
4350 }
4351 return 0;
4352}
4353
4354int
4355peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4356 enum bgp_clear_type stype)
4357{
4358 if (peer->status != Established)
4359 return 0;
4360
4361 if (! peer->afc[afi][safi])
4362 return BGP_ERR_AF_UNCONFIGURED;
4363
paulfee0f4c2004-09-13 05:12:46 +00004364 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4365 {
4366 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4367 return 0;
4368 bgp_check_local_routes_rsclient (peer, afi, safi);
4369 bgp_soft_reconfig_rsclient (peer, afi, safi);
4370 }
4371
paul718e3742002-12-13 20:15:29 +00004372 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4373 bgp_announce_route (peer, afi, safi);
4374
4375 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4376 {
4377 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4378 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4379 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4380 {
4381 struct bgp_filter *filter = &peer->filter[afi][safi];
4382 u_char prefix_type;
4383
4384 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4385 prefix_type = ORF_TYPE_PREFIX;
4386 else
4387 prefix_type = ORF_TYPE_PREFIX_OLD;
4388
4389 if (filter->plist[FILTER_IN].plist)
4390 {
4391 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4392 bgp_route_refresh_send (peer, afi, safi,
4393 prefix_type, REFRESH_DEFER, 1);
4394 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4395 REFRESH_IMMEDIATE, 0);
4396 }
4397 else
4398 {
4399 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4400 bgp_route_refresh_send (peer, afi, safi,
4401 prefix_type, REFRESH_IMMEDIATE, 1);
4402 else
4403 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4404 }
4405 return 0;
4406 }
4407 }
4408
4409 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4410 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4411 {
4412 /* If neighbor has soft reconfiguration inbound flag.
4413 Use Adj-RIB-In database. */
4414 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4415 bgp_soft_reconfig_in (peer, afi, safi);
4416 else
4417 {
4418 /* If neighbor has route refresh capability, send route refresh
4419 message to the peer. */
4420 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4421 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4422 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4423 else
4424 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4425 }
4426 }
4427 return 0;
4428}
4429
paulfd79ac92004-10-13 05:06:08 +00004430/* Display peer uptime.*/
4431/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004432char *
4433peer_uptime (time_t uptime2, char *buf, size_t len)
4434{
4435 time_t uptime1;
4436 struct tm *tm;
4437
4438 /* Check buffer length. */
4439 if (len < BGP_UPTIME_LEN)
4440 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004441 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004442 /* XXX: should return status instead of buf... */
4443 snprintf (buf, len, "<error> ");
4444 return buf;
paul718e3742002-12-13 20:15:29 +00004445 }
4446
4447 /* If there is no connection has been done before print `never'. */
4448 if (uptime2 == 0)
4449 {
4450 snprintf (buf, len, "never ");
4451 return buf;
4452 }
4453
4454 /* Get current time. */
4455 uptime1 = time (NULL);
4456 uptime1 -= uptime2;
4457 tm = gmtime (&uptime1);
4458
4459 /* Making formatted timer strings. */
4460#define ONE_DAY_SECOND 60*60*24
4461#define ONE_WEEK_SECOND 60*60*24*7
4462
4463 if (uptime1 < ONE_DAY_SECOND)
4464 snprintf (buf, len, "%02d:%02d:%02d",
4465 tm->tm_hour, tm->tm_min, tm->tm_sec);
4466 else if (uptime1 < ONE_WEEK_SECOND)
4467 snprintf (buf, len, "%dd%02dh%02dm",
4468 tm->tm_yday, tm->tm_hour, tm->tm_min);
4469 else
4470 snprintf (buf, len, "%02dw%dd%02dh",
4471 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4472 return buf;
4473}
4474
paul94f2b392005-06-28 12:44:16 +00004475static void
paul718e3742002-12-13 20:15:29 +00004476bgp_config_write_filter (struct vty *vty, struct peer *peer,
4477 afi_t afi, safi_t safi)
4478{
4479 struct bgp_filter *filter;
4480 struct bgp_filter *gfilter = NULL;
4481 char *addr;
4482 int in = FILTER_IN;
4483 int out = FILTER_OUT;
4484
4485 addr = peer->host;
4486 filter = &peer->filter[afi][safi];
4487 if (peer->af_group[afi][safi])
4488 gfilter = &peer->group->conf->filter[afi][safi];
4489
4490 /* distribute-list. */
4491 if (filter->dlist[in].name)
4492 if (! gfilter || ! gfilter->dlist[in].name
4493 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4494 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4495 filter->dlist[in].name, VTY_NEWLINE);
4496 if (filter->dlist[out].name && ! gfilter)
4497 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4498 filter->dlist[out].name, VTY_NEWLINE);
4499
4500 /* prefix-list. */
4501 if (filter->plist[in].name)
4502 if (! gfilter || ! gfilter->plist[in].name
4503 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4504 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4505 filter->plist[in].name, VTY_NEWLINE);
4506 if (filter->plist[out].name && ! gfilter)
4507 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4508 filter->plist[out].name, VTY_NEWLINE);
4509
4510 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004511 if (filter->map[RMAP_IN].name)
4512 if (! gfilter || ! gfilter->map[RMAP_IN].name
4513 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004514 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004515 filter->map[RMAP_IN].name, VTY_NEWLINE);
4516 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004517 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004518 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4519 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4520 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4521 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4522 if (filter->map[RMAP_EXPORT].name)
4523 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4524 || strcmp (filter->map[RMAP_EXPORT].name,
4525 gfilter->map[RMAP_EXPORT].name) != 0)
4526 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4527 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004528
4529 /* unsuppress-map */
4530 if (filter->usmap.name && ! gfilter)
4531 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4532 filter->usmap.name, VTY_NEWLINE);
4533
4534 /* filter-list. */
4535 if (filter->aslist[in].name)
4536 if (! gfilter || ! gfilter->aslist[in].name
4537 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4538 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4539 filter->aslist[in].name, VTY_NEWLINE);
4540 if (filter->aslist[out].name && ! gfilter)
4541 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4542 filter->aslist[out].name, VTY_NEWLINE);
4543}
4544
4545/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004546static void
paul718e3742002-12-13 20:15:29 +00004547bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4548 struct peer *peer, afi_t afi, safi_t safi)
4549{
4550 struct bgp_filter *filter;
4551 struct peer *g_peer = NULL;
4552 char buf[SU_ADDRSTRLEN];
4553 char *addr;
4554
4555 filter = &peer->filter[afi][safi];
4556 addr = peer->host;
4557 if (peer_group_active (peer))
4558 g_peer = peer->group->conf;
4559
4560 /************************************
4561 ****** Global to the neighbor ******
4562 ************************************/
4563 if (afi == AFI_IP && safi == SAFI_UNICAST)
4564 {
4565 /* remote-as. */
4566 if (! peer_group_active (peer))
4567 {
4568 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4569 vty_out (vty, " neighbor %s peer-group%s", addr,
4570 VTY_NEWLINE);
4571 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004572 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004573 VTY_NEWLINE);
4574 }
4575 else
4576 {
4577 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004578 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004579 VTY_NEWLINE);
4580 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4581 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4582 peer->group->name, VTY_NEWLINE);
4583 }
4584
4585 /* local-as. */
4586 if (peer->change_local_as)
4587 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004588 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004589 peer->change_local_as,
4590 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4591 " no-prepend" : "", VTY_NEWLINE);
4592
4593 /* Description. */
4594 if (peer->desc)
4595 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4596 VTY_NEWLINE);
4597
4598 /* Shutdown. */
4599 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4600 if (! peer_group_active (peer) ||
4601 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4602 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4603
Paul Jakma0df7c912008-07-21 21:02:49 +00004604 /* Password. */
4605 if (peer->password)
4606 if (!peer_group_active (peer)
4607 || ! g_peer->password
4608 || strcmp (peer->password, g_peer->password) != 0)
4609 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4610 VTY_NEWLINE);
4611
paul718e3742002-12-13 20:15:29 +00004612 /* BGP port. */
4613 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004614 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004615 VTY_NEWLINE);
4616
4617 /* Local interface name. */
4618 if (peer->ifname)
4619 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4620 VTY_NEWLINE);
4621
4622 /* Passive. */
4623 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4624 if (! peer_group_active (peer) ||
4625 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4626 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4627
4628 /* EBGP multihop. */
4629 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4630 if (! peer_group_active (peer) ||
4631 g_peer->ttl != peer->ttl)
4632 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4633 VTY_NEWLINE);
4634
hasso6ffd2072005-02-02 14:50:11 +00004635 /* disable-connected-check. */
4636 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004637 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004638 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4639 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004640
4641 /* Update-source. */
4642 if (peer->update_if)
4643 if (! peer_group_active (peer) || ! g_peer->update_if
4644 || strcmp (g_peer->update_if, peer->update_if) != 0)
4645 vty_out (vty, " neighbor %s update-source %s%s", addr,
4646 peer->update_if, VTY_NEWLINE);
4647 if (peer->update_source)
4648 if (! peer_group_active (peer) || ! g_peer->update_source
4649 || sockunion_cmp (g_peer->update_source,
4650 peer->update_source) != 0)
4651 vty_out (vty, " neighbor %s update-source %s%s", addr,
4652 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4653 VTY_NEWLINE);
4654
paul718e3742002-12-13 20:15:29 +00004655 /* advertisement-interval */
4656 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4657 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4658 addr, peer->v_routeadv, VTY_NEWLINE);
4659
4660 /* timers. */
4661 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4662 && ! peer_group_active (peer))
4663 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4664 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4665
4666 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4667 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4668 peer->connect, VTY_NEWLINE);
4669
4670 /* Default weight. */
4671 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4672 if (! peer_group_active (peer) ||
4673 g_peer->weight != peer->weight)
4674 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4675 VTY_NEWLINE);
4676
paul718e3742002-12-13 20:15:29 +00004677 /* Dynamic capability. */
4678 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4679 if (! peer_group_active (peer) ||
4680 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4681 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4682 VTY_NEWLINE);
4683
4684 /* dont capability negotiation. */
4685 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4686 if (! peer_group_active (peer) ||
4687 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4688 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4689 VTY_NEWLINE);
4690
4691 /* override capability negotiation. */
4692 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4693 if (! peer_group_active (peer) ||
4694 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4695 vty_out (vty, " neighbor %s override-capability%s", addr,
4696 VTY_NEWLINE);
4697
4698 /* strict capability negotiation. */
4699 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4700 if (! peer_group_active (peer) ||
4701 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4702 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4703 VTY_NEWLINE);
4704
4705 if (! peer_group_active (peer))
4706 {
4707 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4708 {
4709 if (peer->afc[AFI_IP][SAFI_UNICAST])
4710 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4711 }
4712 else
4713 {
4714 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4715 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4716 }
4717 }
4718 }
4719
4720
4721 /************************************
4722 ****** Per AF to the neighbor ******
4723 ************************************/
4724
4725 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4726 {
4727 if (peer->af_group[afi][safi])
4728 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4729 peer->group->name, VTY_NEWLINE);
4730 else
4731 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4732 }
4733
4734 /* ORF capability. */
4735 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4736 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4737 if (! peer->af_group[afi][safi])
4738 {
4739 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4740
4741 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4742 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4743 vty_out (vty, " both");
4744 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4745 vty_out (vty, " send");
4746 else
4747 vty_out (vty, " receive");
4748 vty_out (vty, "%s", VTY_NEWLINE);
4749 }
4750
4751 /* Route reflector client. */
4752 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4753 && ! peer->af_group[afi][safi])
4754 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4755 VTY_NEWLINE);
4756
4757 /* Nexthop self. */
4758 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4759 && ! peer->af_group[afi][safi])
4760 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4761
4762 /* Remove private AS. */
4763 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4764 && ! peer->af_group[afi][safi])
4765 vty_out (vty, " neighbor %s remove-private-AS%s",
4766 addr, VTY_NEWLINE);
4767
4768 /* send-community print. */
4769 if (! peer->af_group[afi][safi])
4770 {
4771 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4772 {
4773 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4774 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4775 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4776 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4777 vty_out (vty, " neighbor %s send-community extended%s",
4778 addr, VTY_NEWLINE);
4779 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4780 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4781 }
4782 else
4783 {
4784 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4785 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4786 vty_out (vty, " no neighbor %s send-community both%s",
4787 addr, VTY_NEWLINE);
4788 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4789 vty_out (vty, " no neighbor %s send-community extended%s",
4790 addr, VTY_NEWLINE);
4791 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4792 vty_out (vty, " no neighbor %s send-community%s",
4793 addr, VTY_NEWLINE);
4794 }
4795 }
4796
4797 /* Default information */
4798 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4799 && ! peer->af_group[afi][safi])
4800 {
4801 vty_out (vty, " neighbor %s default-originate", addr);
4802 if (peer->default_rmap[afi][safi].name)
4803 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4804 vty_out (vty, "%s", VTY_NEWLINE);
4805 }
4806
4807 /* Soft reconfiguration inbound. */
4808 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4809 if (! peer->af_group[afi][safi] ||
4810 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4811 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4812 VTY_NEWLINE);
4813
4814 /* maximum-prefix. */
4815 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4816 if (! peer->af_group[afi][safi]
4817 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004818 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004819 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4820 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004821 {
hasso0a486e52005-02-01 20:57:17 +00004822 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4823 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4824 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4825 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4826 vty_out (vty, " warning-only");
4827 if (peer->pmax_restart[afi][safi])
4828 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4829 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004830 }
paul718e3742002-12-13 20:15:29 +00004831
4832 /* Route server client. */
4833 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4834 && ! peer->af_group[afi][safi])
4835 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4836
4837 /* Allow AS in. */
4838 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4839 if (! peer_group_active (peer)
4840 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4841 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4842 {
4843 if (peer->allowas_in[afi][safi] == 3)
4844 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4845 else
4846 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4847 peer->allowas_in[afi][safi], VTY_NEWLINE);
4848 }
4849
4850 /* Filter. */
4851 bgp_config_write_filter (vty, peer, afi, safi);
4852
4853 /* atribute-unchanged. */
4854 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4855 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4856 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4857 && ! peer->af_group[afi][safi])
4858 {
4859 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4860 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4861 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4862 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4863 else
4864 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4865 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4866 " as-path" : "",
4867 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4868 " next-hop" : "",
4869 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4870 " med" : "", VTY_NEWLINE);
4871 }
4872}
4873
4874/* Display "address-family" configuration header. */
4875void
4876bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4877 int *write)
4878{
4879 if (*write)
4880 return;
4881
4882 if (afi == AFI_IP && safi == SAFI_UNICAST)
4883 return;
4884
4885 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4886
4887 if (afi == AFI_IP)
4888 {
4889 if (safi == SAFI_MULTICAST)
4890 vty_out (vty, "ipv4 multicast");
4891 else if (safi == SAFI_MPLS_VPN)
4892 vty_out (vty, "vpnv4 unicast");
4893 }
4894 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004895 {
4896 vty_out (vty, "ipv6");
4897
4898 if (safi == SAFI_MULTICAST)
4899 vty_out (vty, " multicast");
4900 }
paul718e3742002-12-13 20:15:29 +00004901
4902 vty_out (vty, "%s", VTY_NEWLINE);
4903
4904 *write = 1;
4905}
4906
4907/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004908static int
paul718e3742002-12-13 20:15:29 +00004909bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4910 safi_t safi)
4911{
4912 int write = 0;
4913 struct peer *peer;
4914 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004915 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004916
4917 bgp_config_write_network (vty, bgp, afi, safi, &write);
4918
4919 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4920
paul1eb8ef22005-04-07 07:30:20 +00004921 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004922 {
4923 if (group->conf->afc[afi][safi])
4924 {
4925 bgp_config_write_family_header (vty, afi, safi, &write);
4926 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4927 }
4928 }
paul1eb8ef22005-04-07 07:30:20 +00004929 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004930 {
4931 if (peer->afc[afi][safi])
4932 {
4933 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4934 {
4935 bgp_config_write_family_header (vty, afi, safi, &write);
4936 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4937 }
4938 }
4939 }
4940 if (write)
4941 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4942
4943 return write;
4944}
4945
4946int
4947bgp_config_write (struct vty *vty)
4948{
4949 int write = 0;
4950 struct bgp *bgp;
4951 struct peer_group *group;
4952 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004953 struct listnode *node, *nnode;
4954 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004955
4956 /* BGP Multiple instance. */
4957 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4958 {
4959 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4960 write++;
4961 }
4962
4963 /* BGP Config type. */
4964 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4965 {
4966 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4967 write++;
4968 }
4969
4970 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004971 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004972 {
4973 if (write)
4974 vty_out (vty, "!%s", VTY_NEWLINE);
4975
4976 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004977 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004978
4979 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4980 {
4981 if (bgp->name)
4982 vty_out (vty, " view %s", bgp->name);
4983 }
4984 vty_out (vty, "%s", VTY_NEWLINE);
4985
4986 /* No Synchronization */
4987 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4988 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4989
4990 /* BGP fast-external-failover. */
4991 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4992 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4993
4994 /* BGP router ID. */
4995 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4996 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4997 VTY_NEWLINE);
4998
paul848973c2003-08-13 00:32:49 +00004999 /* BGP log-neighbor-changes. */
5000 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5001 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5002
paul718e3742002-12-13 20:15:29 +00005003 /* BGP configuration. */
5004 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5005 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5006
5007 /* BGP default ipv4-unicast. */
5008 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5009 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5010
5011 /* BGP default local-preference. */
5012 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5013 vty_out (vty, " bgp default local-preference %d%s",
5014 bgp->default_local_pref, VTY_NEWLINE);
5015
5016 /* BGP client-to-client reflection. */
5017 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5018 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5019
5020 /* BGP cluster ID. */
5021 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5022 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5023 VTY_NEWLINE);
5024
hassoe0701b72004-05-20 09:19:34 +00005025 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005026 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005027 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5028 VTY_NEWLINE);
5029
5030 /* Confederation peer */
5031 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005032 {
hassoe0701b72004-05-20 09:19:34 +00005033 int i;
paul718e3742002-12-13 20:15:29 +00005034
hassoe0701b72004-05-20 09:19:34 +00005035 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005036
hassoe0701b72004-05-20 09:19:34 +00005037 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005038 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005039
hassoe0701b72004-05-20 09:19:34 +00005040 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005041 }
5042
5043 /* BGP enforce-first-as. */
5044 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5045 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5046
5047 /* BGP deterministic-med. */
5048 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5049 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005050
5051 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005052 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5053 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5054 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005055 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5056 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5057
paul718e3742002-12-13 20:15:29 +00005058 /* BGP bestpath method. */
5059 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5060 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005061 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5062 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005063 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5064 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5065 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5066 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5067 {
5068 vty_out (vty, " bgp bestpath med");
5069 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5070 vty_out (vty, " confed");
5071 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5072 vty_out (vty, " missing-as-worst");
5073 vty_out (vty, "%s", VTY_NEWLINE);
5074 }
5075
5076 /* BGP network import check. */
5077 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5078 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5079
5080 /* BGP scan interval. */
5081 bgp_config_write_scan_time (vty);
5082
5083 /* BGP flag dampening. */
5084 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5085 BGP_CONFIG_DAMPENING))
5086 bgp_config_write_damp (vty);
5087
5088 /* BGP static route configuration. */
5089 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5090
5091 /* BGP redistribute configuration. */
5092 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5093
5094 /* BGP timers configuration. */
5095 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5096 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5097 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5098 bgp->default_holdtime, VTY_NEWLINE);
5099
5100 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005101 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005102 {
5103 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5104 }
5105
5106 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005107 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005108 {
5109 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5110 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5111 }
5112
5113 /* Distance configuration. */
5114 bgp_config_write_distance (vty, bgp);
5115
5116 /* No auto-summary */
5117 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5118 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5119
5120 /* IPv4 multicast configuration. */
5121 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5122
5123 /* IPv4 VPN configuration. */
5124 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5125
5126 /* IPv6 unicast configuration. */
5127 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5128
Paul Jakma37a217a2007-04-10 19:20:29 +00005129 /* IPv6 multicast configuration. */
5130 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5131
paul718e3742002-12-13 20:15:29 +00005132 write++;
5133 }
5134 return write;
5135}
5136
5137void
paul94f2b392005-06-28 12:44:16 +00005138bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005139{
5140 memset (&bgp_master, 0, sizeof (struct bgp_master));
5141
5142 bm = &bgp_master;
5143 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005144 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005145 bm->port = BGP_PORT_DEFAULT;
5146 bm->master = thread_master_create ();
5147 bm->start_time = time (NULL);
5148}
paul200df112005-06-01 11:17:05 +00005149
paul718e3742002-12-13 20:15:29 +00005150
5151void
paul94f2b392005-06-28 12:44:16 +00005152bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005153{
paul718e3742002-12-13 20:15:29 +00005154 /* BGP VTY commands installation. */
5155 bgp_vty_init ();
5156
paul718e3742002-12-13 20:15:29 +00005157 /* Init zebra. */
5158 bgp_zebra_init ();
5159
5160 /* BGP inits. */
5161 bgp_attr_init ();
5162 bgp_debug_init ();
5163 bgp_dump_init ();
5164 bgp_route_init ();
5165 bgp_route_map_init ();
5166 bgp_scan_init ();
5167 bgp_mplsvpn_init ();
5168
5169 /* Access list initialize. */
5170 access_list_init ();
5171 access_list_add_hook (peer_distribute_update);
5172 access_list_delete_hook (peer_distribute_update);
5173
5174 /* Filter list initialize. */
5175 bgp_filter_init ();
5176 as_list_add_hook (peer_aslist_update);
5177 as_list_delete_hook (peer_aslist_update);
5178
5179 /* Prefix list initialize.*/
5180 prefix_list_init ();
5181 prefix_list_add_hook (peer_prefix_list_update);
5182 prefix_list_delete_hook (peer_prefix_list_update);
5183
5184 /* Community list initialize. */
5185 bgp_clist = community_list_init ();
5186
5187#ifdef HAVE_SNMP
5188 bgp_snmp_init ();
5189#endif /* HAVE_SNMP */
5190}
paul545acaf2004-04-20 15:13:15 +00005191
5192void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005193bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005194{
paul545acaf2004-04-20 15:13:15 +00005195 struct bgp *bgp;
5196 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005197 struct listnode *node, *nnode;
5198 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005199
paul1eb8ef22005-04-07 07:30:20 +00005200 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005202 if (peer->status == Established)
5203 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5204 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005205
paul545acaf2004-04-20 15:13:15 +00005206 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005207
paule210cf92005-06-15 19:15:35 +00005208 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005209 {
5210 work_queue_free (bm->process_main_queue);
5211 bm->process_main_queue = NULL;
5212 }
paule210cf92005-06-15 19:15:35 +00005213 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005214 {
5215 work_queue_free (bm->process_rsclient_queue);
5216 bm->process_rsclient_queue = NULL;
5217 }
paul545acaf2004-04-20 15:13:15 +00005218}