blob: 274180b9e918bb0a6d098798b4d72153516d74f9 [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 }
2205 return NULL;
2206}
2207
2208/* If peer is configured at least one address family return 1. */
2209int
2210peer_active (struct peer *peer)
2211{
2212 if (peer->afc[AFI_IP][SAFI_UNICAST]
2213 || peer->afc[AFI_IP][SAFI_MULTICAST]
2214 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2215 || peer->afc[AFI_IP6][SAFI_UNICAST]
2216 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2217 return 1;
2218 return 0;
2219}
2220
2221/* If peer is negotiated at least one address family return 1. */
2222int
2223peer_active_nego (struct peer *peer)
2224{
2225 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2226 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2227 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2228 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2229 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2230 return 1;
2231 return 0;
2232}
2233
2234/* peer_flag_change_type. */
2235enum peer_change_type
2236{
2237 peer_change_none,
2238 peer_change_reset,
2239 peer_change_reset_in,
2240 peer_change_reset_out,
2241};
2242
paul94f2b392005-06-28 12:44:16 +00002243static void
paul718e3742002-12-13 20:15:29 +00002244peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2245 enum peer_change_type type)
2246{
2247 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2248 return;
2249
2250 if (type == peer_change_reset)
2251 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2252 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2253 else if (type == peer_change_reset_in)
2254 {
2255 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2256 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2257 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2258 else
2259 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2260 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2261 }
2262 else if (type == peer_change_reset_out)
2263 bgp_announce_route (peer, afi, safi);
2264}
2265
2266struct peer_flag_action
2267{
2268 /* Peer's flag. */
2269 u_int32_t flag;
2270
2271 /* This flag can be set for peer-group member. */
2272 u_char not_for_member;
2273
2274 /* Action when the flag is changed. */
2275 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002276
2277 /* Peer down cause */
2278 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002279};
2280
Stephen Hemminger03621952009-07-21 16:27:20 -07002281static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002282 {
2283 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2284 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2285 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2286 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2287 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002288 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002289 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002290 { 0, 0, 0 }
2291 };
2292
Stephen Hemminger03621952009-07-21 16:27:20 -07002293static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002294 {
2295 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2296 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2297 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2298 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2299 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2300 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2301 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2302 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2303 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2304 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2305 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2306 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2307 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002308 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002309 { 0, 0, 0 }
2310 };
2311
2312/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002313static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002314peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002315 struct peer_flag_action *action, u_int32_t flag)
2316{
2317 int i;
2318 int found = 0;
2319 int reset_in = 0;
2320 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002321 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002322
2323 /* Check peer's frag action. */
2324 for (i = 0; i < size; i++)
2325 {
2326 match = &action_list[i];
2327
2328 if (match->flag == 0)
2329 break;
2330
2331 if (match->flag & flag)
2332 {
2333 found = 1;
2334
2335 if (match->type == peer_change_reset_in)
2336 reset_in = 1;
2337 if (match->type == peer_change_reset_out)
2338 reset_out = 1;
2339 if (match->type == peer_change_reset)
2340 {
2341 reset_in = 1;
2342 reset_out = 1;
2343 }
2344 if (match->not_for_member)
2345 action->not_for_member = 1;
2346 }
2347 }
2348
2349 /* Set peer clear type. */
2350 if (reset_in && reset_out)
2351 action->type = peer_change_reset;
2352 else if (reset_in)
2353 action->type = peer_change_reset_in;
2354 else if (reset_out)
2355 action->type = peer_change_reset_out;
2356 else
2357 action->type = peer_change_none;
2358
2359 return found;
2360}
2361
paul94f2b392005-06-28 12:44:16 +00002362static void
paul718e3742002-12-13 20:15:29 +00002363peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2364{
2365 if (flag == PEER_FLAG_SHUTDOWN)
2366 {
2367 if (CHECK_FLAG (peer->flags, flag))
2368 {
hasso93406d82005-02-02 14:40:33 +00002369 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2370 peer_nsf_stop (peer);
2371
hasso0a486e52005-02-01 20:57:17 +00002372 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2373 if (peer->t_pmax_restart)
2374 {
2375 BGP_TIMER_OFF (peer->t_pmax_restart);
2376 if (BGP_DEBUG (events, EVENTS))
2377 zlog_debug ("%s Maximum-prefix restart timer canceled",
2378 peer->host);
2379 }
2380
hasso93406d82005-02-02 14:40:33 +00002381 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2382 peer_nsf_stop (peer);
2383
paul718e3742002-12-13 20:15:29 +00002384 if (peer->status == Established)
2385 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2386 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2387 else
2388 BGP_EVENT_ADD (peer, BGP_Stop);
2389 }
2390 else
2391 {
2392 peer->v_start = BGP_INIT_START_TIMER;
2393 BGP_EVENT_ADD (peer, BGP_Stop);
2394 }
2395 }
2396 else if (peer->status == Established)
2397 {
hassoc9502432005-02-01 22:01:48 +00002398 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2399 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2400 else if (flag == PEER_FLAG_PASSIVE)
2401 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002402 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002403 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002404
hassoc9502432005-02-01 22:01:48 +00002405 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2406 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002407 }
2408 else
2409 BGP_EVENT_ADD (peer, BGP_Stop);
2410}
2411
2412/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002413static int
paul718e3742002-12-13 20:15:29 +00002414peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2415{
2416 int found;
2417 int size;
2418 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002419 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002420 struct peer_flag_action action;
2421
2422 memset (&action, 0, sizeof (struct peer_flag_action));
2423 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2424
2425 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2426
2427 /* No flag action is found. */
2428 if (! found)
2429 return BGP_ERR_INVALID_FLAG;
2430
2431 /* Not for peer-group member. */
2432 if (action.not_for_member && peer_group_active (peer))
2433 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2434
2435 /* When unset the peer-group member's flag we have to check
2436 peer-group configuration. */
2437 if (! set && peer_group_active (peer))
2438 if (CHECK_FLAG (peer->group->conf->flags, flag))
2439 {
2440 if (flag == PEER_FLAG_SHUTDOWN)
2441 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2442 else
2443 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2444 }
2445
2446 /* Flag conflict check. */
2447 if (set
2448 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2449 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2450 return BGP_ERR_PEER_FLAG_CONFLICT;
2451
2452 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2453 {
2454 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2455 return 0;
2456 if (! set && ! CHECK_FLAG (peer->flags, flag))
2457 return 0;
2458 }
2459
2460 if (set)
2461 SET_FLAG (peer->flags, flag);
2462 else
2463 UNSET_FLAG (peer->flags, flag);
2464
2465 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2466 {
2467 if (action.type == peer_change_reset)
2468 peer_flag_modify_action (peer, flag);
2469
2470 return 0;
2471 }
2472
2473 /* peer-group member updates. */
2474 group = peer->group;
2475
paul1eb8ef22005-04-07 07:30:20 +00002476 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002477 {
2478 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2479 continue;
2480
2481 if (! set && ! CHECK_FLAG (peer->flags, flag))
2482 continue;
2483
2484 if (set)
2485 SET_FLAG (peer->flags, flag);
2486 else
2487 UNSET_FLAG (peer->flags, flag);
2488
2489 if (action.type == peer_change_reset)
2490 peer_flag_modify_action (peer, flag);
2491 }
2492 return 0;
2493}
2494
2495int
2496peer_flag_set (struct peer *peer, u_int32_t flag)
2497{
2498 return peer_flag_modify (peer, flag, 1);
2499}
2500
2501int
2502peer_flag_unset (struct peer *peer, u_int32_t flag)
2503{
2504 return peer_flag_modify (peer, flag, 0);
2505}
2506
paul94f2b392005-06-28 12:44:16 +00002507static int
paul718e3742002-12-13 20:15:29 +00002508peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2509{
2510 if (peer->af_group[afi][safi])
2511 return 1;
2512 return 0;
2513}
2514
paul94f2b392005-06-28 12:44:16 +00002515static int
paul718e3742002-12-13 20:15:29 +00002516peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2517 int set)
2518{
2519 int found;
2520 int size;
paul1eb8ef22005-04-07 07:30:20 +00002521 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002522 struct peer_group *group;
2523 struct peer_flag_action action;
2524
2525 memset (&action, 0, sizeof (struct peer_flag_action));
2526 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2527
2528 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2529
2530 /* No flag action is found. */
2531 if (! found)
2532 return BGP_ERR_INVALID_FLAG;
2533
2534 /* Adress family must be activated. */
2535 if (! peer->afc[afi][safi])
2536 return BGP_ERR_PEER_INACTIVE;
2537
2538 /* Not for peer-group member. */
2539 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2540 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2541
2542 /* Spcecial check for reflector client. */
2543 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2544 && peer_sort (peer) != BGP_PEER_IBGP)
2545 return BGP_ERR_NOT_INTERNAL_PEER;
2546
2547 /* Spcecial check for remove-private-AS. */
2548 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2549 && peer_sort (peer) == BGP_PEER_IBGP)
2550 return BGP_ERR_REMOVE_PRIVATE_AS;
2551
2552 /* When unset the peer-group member's flag we have to check
2553 peer-group configuration. */
2554 if (! set && peer->af_group[afi][safi])
2555 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2556 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2557
2558 /* When current flag configuration is same as requested one. */
2559 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2560 {
2561 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2562 return 0;
2563 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2564 return 0;
2565 }
2566
2567 if (set)
2568 SET_FLAG (peer->af_flags[afi][safi], flag);
2569 else
2570 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2571
2572 /* Execute action when peer is established. */
2573 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2574 && peer->status == Established)
2575 {
2576 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2577 bgp_clear_adj_in (peer, afi, safi);
2578 else
hassoe0701b72004-05-20 09:19:34 +00002579 {
2580 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2581 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2582 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2583 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2584 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2585 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2586 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2587 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2588
2589 peer_change_action (peer, afi, safi, action.type);
2590 }
2591
paul718e3742002-12-13 20:15:29 +00002592 }
2593
2594 /* Peer group member updates. */
2595 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2596 {
2597 group = peer->group;
2598
paul1eb8ef22005-04-07 07:30:20 +00002599 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002600 {
2601 if (! peer->af_group[afi][safi])
2602 continue;
2603
2604 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2605 continue;
2606
2607 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2608 continue;
2609
2610 if (set)
2611 SET_FLAG (peer->af_flags[afi][safi], flag);
2612 else
2613 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2614
2615 if (peer->status == Established)
2616 {
2617 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2618 bgp_clear_adj_in (peer, afi, safi);
2619 else
hassoe0701b72004-05-20 09:19:34 +00002620 {
2621 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2622 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2623 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2624 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2625 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2626 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2627 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2628 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2629
2630 peer_change_action (peer, afi, safi, action.type);
2631 }
paul718e3742002-12-13 20:15:29 +00002632 }
2633 }
2634 }
2635 return 0;
2636}
2637
2638int
2639peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2640{
2641 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2642}
2643
2644int
2645peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2646{
2647 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2648}
2649
2650/* EBGP multihop configuration. */
2651int
2652peer_ebgp_multihop_set (struct peer *peer, int ttl)
2653{
2654 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002655 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002656
2657 if (peer_sort (peer) == BGP_PEER_IBGP)
2658 return 0;
2659
2660 peer->ttl = ttl;
2661
2662 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2663 {
pauleb821182004-05-01 08:44:08 +00002664 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2665 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002666 }
2667 else
2668 {
2669 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002670 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002671 {
2672 if (peer_sort (peer) == BGP_PEER_IBGP)
2673 continue;
paul718e3742002-12-13 20:15:29 +00002674
pauleb821182004-05-01 08:44:08 +00002675 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002676
pauleb821182004-05-01 08:44:08 +00002677 if (peer->fd >= 0)
2678 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2679 }
paul718e3742002-12-13 20:15:29 +00002680 }
2681 return 0;
2682}
2683
2684int
2685peer_ebgp_multihop_unset (struct peer *peer)
2686{
2687 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002688 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002689
2690 if (peer_sort (peer) == BGP_PEER_IBGP)
2691 return 0;
2692
2693 if (peer_group_active (peer))
2694 peer->ttl = peer->group->conf->ttl;
2695 else
2696 peer->ttl = 1;
2697
2698 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2699 {
pauleb821182004-05-01 08:44:08 +00002700 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2701 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002702 }
2703 else
2704 {
2705 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002706 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002707 {
2708 if (peer_sort (peer) == BGP_PEER_IBGP)
2709 continue;
paul718e3742002-12-13 20:15:29 +00002710
pauleb821182004-05-01 08:44:08 +00002711 peer->ttl = 1;
2712
2713 if (peer->fd >= 0)
2714 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2715 }
paul718e3742002-12-13 20:15:29 +00002716 }
2717 return 0;
2718}
2719
2720/* Neighbor description. */
2721int
2722peer_description_set (struct peer *peer, char *desc)
2723{
2724 if (peer->desc)
2725 XFREE (MTYPE_PEER_DESC, peer->desc);
2726
2727 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2728
2729 return 0;
2730}
2731
2732int
2733peer_description_unset (struct peer *peer)
2734{
2735 if (peer->desc)
2736 XFREE (MTYPE_PEER_DESC, peer->desc);
2737
2738 peer->desc = NULL;
2739
2740 return 0;
2741}
2742
2743/* Neighbor update-source. */
2744int
paulfd79ac92004-10-13 05:06:08 +00002745peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002746{
2747 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002748 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002749
2750 if (peer->update_if)
2751 {
2752 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2753 && strcmp (peer->update_if, ifname) == 0)
2754 return 0;
2755
2756 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2757 peer->update_if = NULL;
2758 }
2759
2760 if (peer->update_source)
2761 {
2762 sockunion_free (peer->update_source);
2763 peer->update_source = NULL;
2764 }
2765
2766 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2767
2768 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2769 {
2770 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002771 {
2772 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2773 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2774 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2775 }
paul718e3742002-12-13 20:15:29 +00002776 else
2777 BGP_EVENT_ADD (peer, BGP_Stop);
2778 return 0;
2779 }
2780
2781 /* peer-group member updates. */
2782 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002783 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002784 {
2785 if (peer->update_if)
2786 {
2787 if (strcmp (peer->update_if, ifname) == 0)
2788 continue;
2789
2790 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2791 peer->update_if = NULL;
2792 }
2793
2794 if (peer->update_source)
2795 {
2796 sockunion_free (peer->update_source);
2797 peer->update_source = NULL;
2798 }
2799
2800 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2801
2802 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002803 {
2804 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2805 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2806 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2807 }
paul718e3742002-12-13 20:15:29 +00002808 else
2809 BGP_EVENT_ADD (peer, BGP_Stop);
2810 }
2811 return 0;
2812}
2813
2814int
2815peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2816{
2817 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002818 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002819
2820 if (peer->update_source)
2821 {
2822 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2823 && sockunion_cmp (peer->update_source, su) == 0)
2824 return 0;
2825 sockunion_free (peer->update_source);
2826 peer->update_source = NULL;
2827 }
2828
2829 if (peer->update_if)
2830 {
2831 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2832 peer->update_if = NULL;
2833 }
2834
2835 peer->update_source = sockunion_dup (su);
2836
2837 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2838 {
2839 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002840 {
2841 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2842 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2843 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2844 }
paul718e3742002-12-13 20:15:29 +00002845 else
2846 BGP_EVENT_ADD (peer, BGP_Stop);
2847 return 0;
2848 }
2849
2850 /* peer-group member updates. */
2851 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002852 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002853 {
2854 if (peer->update_source)
2855 {
2856 if (sockunion_cmp (peer->update_source, su) == 0)
2857 continue;
2858 sockunion_free (peer->update_source);
2859 peer->update_source = NULL;
2860 }
2861
2862 if (peer->update_if)
2863 {
2864 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2865 peer->update_if = NULL;
2866 }
2867
2868 peer->update_source = sockunion_dup (su);
2869
2870 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002871 {
2872 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2873 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2874 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2875 }
paul718e3742002-12-13 20:15:29 +00002876 else
2877 BGP_EVENT_ADD (peer, BGP_Stop);
2878 }
2879 return 0;
2880}
2881
2882int
2883peer_update_source_unset (struct peer *peer)
2884{
2885 union sockunion *su;
2886 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002887 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002888
2889 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2890 && ! peer->update_source
2891 && ! peer->update_if)
2892 return 0;
2893
2894 if (peer->update_source)
2895 {
2896 sockunion_free (peer->update_source);
2897 peer->update_source = NULL;
2898 }
2899 if (peer->update_if)
2900 {
2901 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2902 peer->update_if = NULL;
2903 }
2904
2905 if (peer_group_active (peer))
2906 {
2907 group = peer->group;
2908
2909 if (group->conf->update_source)
2910 {
2911 su = sockunion_dup (group->conf->update_source);
2912 peer->update_source = su;
2913 }
2914 else if (group->conf->update_if)
2915 peer->update_if =
2916 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2917 }
2918
2919 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2920 {
2921 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002922 {
2923 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2924 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2925 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2926 }
paul718e3742002-12-13 20:15:29 +00002927 else
2928 BGP_EVENT_ADD (peer, BGP_Stop);
2929 return 0;
2930 }
2931
2932 /* peer-group member updates. */
2933 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002934 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002935 {
2936 if (! peer->update_source && ! peer->update_if)
2937 continue;
2938
2939 if (peer->update_source)
2940 {
2941 sockunion_free (peer->update_source);
2942 peer->update_source = NULL;
2943 }
2944
2945 if (peer->update_if)
2946 {
2947 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2948 peer->update_if = NULL;
2949 }
2950
2951 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002952 {
2953 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2954 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2955 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2956 }
paul718e3742002-12-13 20:15:29 +00002957 else
2958 BGP_EVENT_ADD (peer, BGP_Stop);
2959 }
2960 return 0;
2961}
2962
2963int
2964peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002965 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002966{
2967 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002968 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002969
2970 /* Adress family must be activated. */
2971 if (! peer->afc[afi][safi])
2972 return BGP_ERR_PEER_INACTIVE;
2973
2974 /* Default originate can't be used for peer group memeber. */
2975 if (peer_is_group_member (peer, afi, safi))
2976 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2977
2978 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2979 || (rmap && ! peer->default_rmap[afi][safi].name)
2980 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2981 {
2982 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2983
2984 if (rmap)
2985 {
2986 if (peer->default_rmap[afi][safi].name)
2987 free (peer->default_rmap[afi][safi].name);
2988 peer->default_rmap[afi][safi].name = strdup (rmap);
2989 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2990 }
2991 }
2992
2993 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2994 {
2995 if (peer->status == Established && peer->afc_nego[afi][safi])
2996 bgp_default_originate (peer, afi, safi, 0);
2997 return 0;
2998 }
2999
3000 /* peer-group member updates. */
3001 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003002 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003003 {
3004 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3005
3006 if (rmap)
3007 {
3008 if (peer->default_rmap[afi][safi].name)
3009 free (peer->default_rmap[afi][safi].name);
3010 peer->default_rmap[afi][safi].name = strdup (rmap);
3011 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3012 }
3013
3014 if (peer->status == Established && peer->afc_nego[afi][safi])
3015 bgp_default_originate (peer, afi, safi, 0);
3016 }
3017 return 0;
3018}
3019
3020int
3021peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3022{
3023 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003024 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003025
3026 /* Adress family must be activated. */
3027 if (! peer->afc[afi][safi])
3028 return BGP_ERR_PEER_INACTIVE;
3029
3030 /* Default originate can't be used for peer group memeber. */
3031 if (peer_is_group_member (peer, afi, safi))
3032 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3033
3034 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3035 {
3036 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3037
3038 if (peer->default_rmap[afi][safi].name)
3039 free (peer->default_rmap[afi][safi].name);
3040 peer->default_rmap[afi][safi].name = NULL;
3041 peer->default_rmap[afi][safi].map = NULL;
3042 }
3043
3044 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3045 {
3046 if (peer->status == Established && peer->afc_nego[afi][safi])
3047 bgp_default_originate (peer, afi, safi, 1);
3048 return 0;
3049 }
3050
3051 /* peer-group member updates. */
3052 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003053 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003054 {
3055 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3056
3057 if (peer->default_rmap[afi][safi].name)
3058 free (peer->default_rmap[afi][safi].name);
3059 peer->default_rmap[afi][safi].name = NULL;
3060 peer->default_rmap[afi][safi].map = NULL;
3061
3062 if (peer->status == Established && peer->afc_nego[afi][safi])
3063 bgp_default_originate (peer, afi, safi, 1);
3064 }
3065 return 0;
3066}
3067
3068int
3069peer_port_set (struct peer *peer, u_int16_t port)
3070{
3071 peer->port = port;
3072 return 0;
3073}
3074
3075int
3076peer_port_unset (struct peer *peer)
3077{
3078 peer->port = BGP_PORT_DEFAULT;
3079 return 0;
3080}
3081
3082/* neighbor weight. */
3083int
3084peer_weight_set (struct peer *peer, u_int16_t weight)
3085{
3086 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003087 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003088
3089 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3090 peer->weight = weight;
3091
3092 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3093 return 0;
3094
3095 /* peer-group member updates. */
3096 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003097 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003098 {
3099 peer->weight = group->conf->weight;
3100 }
3101 return 0;
3102}
3103
3104int
3105peer_weight_unset (struct peer *peer)
3106{
3107 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003108 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003109
3110 /* Set default weight. */
3111 if (peer_group_active (peer))
3112 peer->weight = peer->group->conf->weight;
3113 else
3114 peer->weight = 0;
3115
3116 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3117
3118 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3119 return 0;
3120
3121 /* peer-group member updates. */
3122 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003123 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003124 {
3125 peer->weight = 0;
3126 }
3127 return 0;
3128}
3129
3130int
3131peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3132{
3133 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003134 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003135
3136 /* Not for peer group memeber. */
3137 if (peer_group_active (peer))
3138 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3139
3140 /* keepalive value check. */
3141 if (keepalive > 65535)
3142 return BGP_ERR_INVALID_VALUE;
3143
3144 /* Holdtime value check. */
3145 if (holdtime > 65535)
3146 return BGP_ERR_INVALID_VALUE;
3147
3148 /* Holdtime value must be either 0 or greater than 3. */
3149 if (holdtime < 3 && holdtime != 0)
3150 return BGP_ERR_INVALID_VALUE;
3151
3152 /* Set value to the configuration. */
3153 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3154 peer->holdtime = holdtime;
3155 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3156
3157 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3158 return 0;
3159
3160 /* peer-group member updates. */
3161 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003162 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003163 {
3164 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3165 peer->holdtime = group->conf->holdtime;
3166 peer->keepalive = group->conf->keepalive;
3167 }
3168 return 0;
3169}
3170
3171int
3172peer_timers_unset (struct peer *peer)
3173{
3174 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003175 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003176
3177 if (peer_group_active (peer))
3178 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3179
3180 /* Clear configuration. */
3181 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3182 peer->keepalive = 0;
3183 peer->holdtime = 0;
3184
3185 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3186 return 0;
3187
3188 /* peer-group member updates. */
3189 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003190 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003191 {
3192 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3193 peer->holdtime = 0;
3194 peer->keepalive = 0;
3195 }
3196
3197 return 0;
3198}
3199
3200int
3201peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3202{
3203 if (peer_group_active (peer))
3204 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3205
3206 if (connect > 65535)
3207 return BGP_ERR_INVALID_VALUE;
3208
3209 /* Set value to the configuration. */
3210 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3211 peer->connect = connect;
3212
3213 /* Set value to timer setting. */
3214 peer->v_connect = connect;
3215
3216 return 0;
3217}
3218
3219int
3220peer_timers_connect_unset (struct peer *peer)
3221{
3222 if (peer_group_active (peer))
3223 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3224
3225 /* Clear configuration. */
3226 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3227 peer->connect = 0;
3228
3229 /* Set timer setting to default value. */
3230 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3231
3232 return 0;
3233}
3234
3235int
3236peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3237{
3238 if (peer_group_active (peer))
3239 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3240
3241 if (routeadv > 600)
3242 return BGP_ERR_INVALID_VALUE;
3243
3244 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3245 peer->routeadv = routeadv;
3246 peer->v_routeadv = routeadv;
3247
3248 return 0;
3249}
3250
3251int
3252peer_advertise_interval_unset (struct peer *peer)
3253{
3254 if (peer_group_active (peer))
3255 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3256
3257 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3258 peer->routeadv = 0;
3259
3260 if (peer_sort (peer) == BGP_PEER_IBGP)
3261 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3262 else
3263 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3264
3265 return 0;
3266}
3267
paul718e3742002-12-13 20:15:29 +00003268/* neighbor interface */
3269int
paulfd79ac92004-10-13 05:06:08 +00003270peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003271{
3272 if (peer->ifname)
3273 free (peer->ifname);
3274 peer->ifname = strdup (str);
3275
3276 return 0;
3277}
3278
3279int
3280peer_interface_unset (struct peer *peer)
3281{
3282 if (peer->ifname)
3283 free (peer->ifname);
3284 peer->ifname = NULL;
3285
3286 return 0;
3287}
3288
3289/* Allow-as in. */
3290int
3291peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3292{
3293 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003294 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003295
3296 if (allow_num < 1 || allow_num > 10)
3297 return BGP_ERR_INVALID_VALUE;
3298
3299 if (peer->allowas_in[afi][safi] != allow_num)
3300 {
3301 peer->allowas_in[afi][safi] = allow_num;
3302 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3303 peer_change_action (peer, afi, safi, peer_change_reset_in);
3304 }
3305
3306 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3307 return 0;
3308
3309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003311 {
3312 if (peer->allowas_in[afi][safi] != allow_num)
3313 {
3314 peer->allowas_in[afi][safi] = allow_num;
3315 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3316 peer_change_action (peer, afi, safi, peer_change_reset_in);
3317 }
3318
3319 }
3320 return 0;
3321}
3322
3323int
3324peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3325{
3326 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003327 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003328
3329 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3330 {
3331 peer->allowas_in[afi][safi] = 0;
3332 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3333 }
3334
3335 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3336 return 0;
3337
3338 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003339 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003340 {
3341 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3342 {
3343 peer->allowas_in[afi][safi] = 0;
3344 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3345 }
3346 }
3347 return 0;
3348}
3349
3350int
3351peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3352{
3353 struct bgp *bgp = peer->bgp;
3354 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003355 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003356
3357 if (peer_sort (peer) != BGP_PEER_EBGP
3358 && peer_sort (peer) != BGP_PEER_INTERNAL)
3359 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3360
3361 if (bgp->as == as)
3362 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3363
3364 if (peer_group_active (peer))
3365 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3366
3367 if (peer->change_local_as == as &&
3368 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3369 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3370 return 0;
3371
3372 peer->change_local_as = as;
3373 if (no_prepend)
3374 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3375 else
3376 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3377
3378 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3379 {
3380 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003381 {
3382 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3383 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3384 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3385 }
paul718e3742002-12-13 20:15:29 +00003386 else
3387 BGP_EVENT_ADD (peer, BGP_Stop);
3388
3389 return 0;
3390 }
3391
3392 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003393 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003394 {
3395 peer->change_local_as = as;
3396 if (no_prepend)
3397 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3398 else
3399 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3400
3401 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003402 {
3403 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3404 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3405 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3406 }
paul718e3742002-12-13 20:15:29 +00003407 else
3408 BGP_EVENT_ADD (peer, BGP_Stop);
3409 }
3410
3411 return 0;
3412}
3413
3414int
3415peer_local_as_unset (struct peer *peer)
3416{
3417 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003418 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003419
3420 if (peer_group_active (peer))
3421 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3422
3423 if (! peer->change_local_as)
3424 return 0;
3425
3426 peer->change_local_as = 0;
3427 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3428
3429 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3430 {
3431 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003432 {
3433 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3434 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3435 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3436 }
paul718e3742002-12-13 20:15:29 +00003437 else
3438 BGP_EVENT_ADD (peer, BGP_Stop);
3439
3440 return 0;
3441 }
3442
3443 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003444 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003445 {
3446 peer->change_local_as = 0;
3447 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3448
3449 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003450 {
3451 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3452 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3453 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3454 }
paul718e3742002-12-13 20:15:29 +00003455 else
3456 BGP_EVENT_ADD (peer, BGP_Stop);
3457 }
3458 return 0;
3459}
3460
Paul Jakma0df7c912008-07-21 21:02:49 +00003461/* Set password for authenticating with the peer. */
3462int
3463peer_password_set (struct peer *peer, const char *password)
3464{
3465 struct listnode *nn, *nnode;
3466 int len = password ? strlen(password) : 0;
3467 int ret = BGP_SUCCESS;
3468
3469 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3470 return BGP_ERR_INVALID_VALUE;
3471
3472 if (peer->password && strcmp (peer->password, password) == 0
3473 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3474 return 0;
3475
3476 if (peer->password)
3477 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3478
3479 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3480
3481 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3482 {
3483 if (peer->status == Established)
3484 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3485 else
3486 BGP_EVENT_ADD (peer, BGP_Stop);
3487
3488 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3489 }
3490
3491 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3492 {
3493 if (peer->password && strcmp (peer->password, password) == 0)
3494 continue;
3495
3496 if (peer->password)
3497 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3498
3499 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3500
3501 if (peer->status == Established)
3502 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3503 else
3504 BGP_EVENT_ADD (peer, BGP_Stop);
3505
3506 if (bgp_md5_set (peer) < 0)
3507 ret = BGP_ERR_TCPSIG_FAILED;
3508 }
3509
3510 return ret;
3511}
3512
3513int
3514peer_password_unset (struct peer *peer)
3515{
3516 struct listnode *nn, *nnode;
3517
3518 if (!peer->password
3519 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3520 return 0;
3521
3522 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3523 {
3524 if (peer_group_active (peer)
3525 && peer->group->conf->password
3526 && strcmp (peer->group->conf->password, peer->password) == 0)
3527 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3528
3529 if (peer->status == Established)
3530 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3531 else
3532 BGP_EVENT_ADD (peer, BGP_Stop);
3533
3534 if (peer->password)
3535 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3536
3537 peer->password = NULL;
3538
3539 bgp_md5_set (peer);
3540
3541 return 0;
3542 }
3543
3544 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3545 peer->password = NULL;
3546
3547 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3548 {
3549 if (!peer->password)
3550 continue;
3551
3552 if (peer->status == Established)
3553 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3554 else
3555 BGP_EVENT_ADD (peer, BGP_Stop);
3556
3557 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3558 peer->password = NULL;
3559
3560 bgp_md5_set (peer);
3561 }
3562
3563 return 0;
3564}
3565
paul718e3742002-12-13 20:15:29 +00003566/* Set distribute list to the peer. */
3567int
3568peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003569 const char *name)
paul718e3742002-12-13 20:15:29 +00003570{
3571 struct bgp_filter *filter;
3572 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003573 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003574
3575 if (! peer->afc[afi][safi])
3576 return BGP_ERR_PEER_INACTIVE;
3577
3578 if (direct != FILTER_IN && direct != FILTER_OUT)
3579 return BGP_ERR_INVALID_VALUE;
3580
3581 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3582 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3583
3584 filter = &peer->filter[afi][safi];
3585
3586 if (filter->plist[direct].name)
3587 return BGP_ERR_PEER_FILTER_CONFLICT;
3588
3589 if (filter->dlist[direct].name)
3590 free (filter->dlist[direct].name);
3591 filter->dlist[direct].name = strdup (name);
3592 filter->dlist[direct].alist = access_list_lookup (afi, name);
3593
3594 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3595 return 0;
3596
3597 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003598 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003599 {
3600 filter = &peer->filter[afi][safi];
3601
3602 if (! peer->af_group[afi][safi])
3603 continue;
3604
3605 if (filter->dlist[direct].name)
3606 free (filter->dlist[direct].name);
3607 filter->dlist[direct].name = strdup (name);
3608 filter->dlist[direct].alist = access_list_lookup (afi, name);
3609 }
3610
3611 return 0;
3612}
3613
3614int
3615peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3616{
3617 struct bgp_filter *filter;
3618 struct bgp_filter *gfilter;
3619 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003620 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003621
3622 if (! peer->afc[afi][safi])
3623 return BGP_ERR_PEER_INACTIVE;
3624
3625 if (direct != FILTER_IN && direct != FILTER_OUT)
3626 return BGP_ERR_INVALID_VALUE;
3627
3628 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3629 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3630
3631 filter = &peer->filter[afi][safi];
3632
3633 /* apply peer-group filter */
3634 if (peer->af_group[afi][safi])
3635 {
3636 gfilter = &peer->group->conf->filter[afi][safi];
3637
3638 if (gfilter->dlist[direct].name)
3639 {
3640 if (filter->dlist[direct].name)
3641 free (filter->dlist[direct].name);
3642 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3643 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3644 return 0;
3645 }
3646 }
3647
3648 if (filter->dlist[direct].name)
3649 free (filter->dlist[direct].name);
3650 filter->dlist[direct].name = NULL;
3651 filter->dlist[direct].alist = NULL;
3652
3653 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3654 return 0;
3655
3656 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003657 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003658 {
3659 filter = &peer->filter[afi][safi];
3660
3661 if (! peer->af_group[afi][safi])
3662 continue;
3663
3664 if (filter->dlist[direct].name)
3665 free (filter->dlist[direct].name);
3666 filter->dlist[direct].name = NULL;
3667 filter->dlist[direct].alist = NULL;
3668 }
3669
3670 return 0;
3671}
3672
3673/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003674static void
paul718e3742002-12-13 20:15:29 +00003675peer_distribute_update (struct access_list *access)
3676{
3677 afi_t afi;
3678 safi_t safi;
3679 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003680 struct listnode *mnode, *mnnode;
3681 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003682 struct bgp *bgp;
3683 struct peer *peer;
3684 struct peer_group *group;
3685 struct bgp_filter *filter;
3686
paul1eb8ef22005-04-07 07:30:20 +00003687 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003688 {
paul1eb8ef22005-04-07 07:30:20 +00003689 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003690 {
3691 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3692 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3693 {
3694 filter = &peer->filter[afi][safi];
3695
3696 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3697 {
3698 if (filter->dlist[direct].name)
3699 filter->dlist[direct].alist =
3700 access_list_lookup (afi, filter->dlist[direct].name);
3701 else
3702 filter->dlist[direct].alist = NULL;
3703 }
3704 }
3705 }
paul1eb8ef22005-04-07 07:30:20 +00003706 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003707 {
3708 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3709 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3710 {
3711 filter = &group->conf->filter[afi][safi];
3712
3713 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3714 {
3715 if (filter->dlist[direct].name)
3716 filter->dlist[direct].alist =
3717 access_list_lookup (afi, filter->dlist[direct].name);
3718 else
3719 filter->dlist[direct].alist = NULL;
3720 }
3721 }
3722 }
3723 }
3724}
3725
3726/* Set prefix list to the peer. */
3727int
3728peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003729 const char *name)
paul718e3742002-12-13 20:15:29 +00003730{
3731 struct bgp_filter *filter;
3732 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003733 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003734
3735 if (! peer->afc[afi][safi])
3736 return BGP_ERR_PEER_INACTIVE;
3737
3738 if (direct != FILTER_IN && direct != FILTER_OUT)
3739 return BGP_ERR_INVALID_VALUE;
3740
3741 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3742 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3743
3744 filter = &peer->filter[afi][safi];
3745
3746 if (filter->dlist[direct].name)
3747 return BGP_ERR_PEER_FILTER_CONFLICT;
3748
3749 if (filter->plist[direct].name)
3750 free (filter->plist[direct].name);
3751 filter->plist[direct].name = strdup (name);
3752 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3753
3754 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3755 return 0;
3756
3757 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003758 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003759 {
3760 filter = &peer->filter[afi][safi];
3761
3762 if (! peer->af_group[afi][safi])
3763 continue;
3764
3765 if (filter->plist[direct].name)
3766 free (filter->plist[direct].name);
3767 filter->plist[direct].name = strdup (name);
3768 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3769 }
3770 return 0;
3771}
3772
3773int
3774peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3775{
3776 struct bgp_filter *filter;
3777 struct bgp_filter *gfilter;
3778 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003779 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003780
3781 if (! peer->afc[afi][safi])
3782 return BGP_ERR_PEER_INACTIVE;
3783
3784 if (direct != FILTER_IN && direct != FILTER_OUT)
3785 return BGP_ERR_INVALID_VALUE;
3786
3787 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3788 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3789
3790 filter = &peer->filter[afi][safi];
3791
3792 /* apply peer-group filter */
3793 if (peer->af_group[afi][safi])
3794 {
3795 gfilter = &peer->group->conf->filter[afi][safi];
3796
3797 if (gfilter->plist[direct].name)
3798 {
3799 if (filter->plist[direct].name)
3800 free (filter->plist[direct].name);
3801 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3802 filter->plist[direct].plist = gfilter->plist[direct].plist;
3803 return 0;
3804 }
3805 }
3806
3807 if (filter->plist[direct].name)
3808 free (filter->plist[direct].name);
3809 filter->plist[direct].name = NULL;
3810 filter->plist[direct].plist = NULL;
3811
3812 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3813 return 0;
3814
3815 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003816 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003817 {
3818 filter = &peer->filter[afi][safi];
3819
3820 if (! peer->af_group[afi][safi])
3821 continue;
3822
3823 if (filter->plist[direct].name)
3824 free (filter->plist[direct].name);
3825 filter->plist[direct].name = NULL;
3826 filter->plist[direct].plist = NULL;
3827 }
3828
3829 return 0;
3830}
3831
3832/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003833static void
paul718e3742002-12-13 20:15:29 +00003834peer_prefix_list_update (struct prefix_list *plist)
3835{
paul1eb8ef22005-04-07 07:30:20 +00003836 struct listnode *mnode, *mnnode;
3837 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003838 struct bgp *bgp;
3839 struct peer *peer;
3840 struct peer_group *group;
3841 struct bgp_filter *filter;
3842 afi_t afi;
3843 safi_t safi;
3844 int direct;
3845
paul1eb8ef22005-04-07 07:30:20 +00003846 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003847 {
paul1eb8ef22005-04-07 07:30:20 +00003848 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003849 {
3850 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3851 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3852 {
3853 filter = &peer->filter[afi][safi];
3854
3855 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3856 {
3857 if (filter->plist[direct].name)
3858 filter->plist[direct].plist =
3859 prefix_list_lookup (afi, filter->plist[direct].name);
3860 else
3861 filter->plist[direct].plist = NULL;
3862 }
3863 }
3864 }
paul1eb8ef22005-04-07 07:30:20 +00003865 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003866 {
3867 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3868 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3869 {
3870 filter = &group->conf->filter[afi][safi];
3871
3872 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3873 {
3874 if (filter->plist[direct].name)
3875 filter->plist[direct].plist =
3876 prefix_list_lookup (afi, filter->plist[direct].name);
3877 else
3878 filter->plist[direct].plist = NULL;
3879 }
3880 }
3881 }
3882 }
3883}
3884
3885int
3886peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003887 const char *name)
paul718e3742002-12-13 20:15:29 +00003888{
3889 struct bgp_filter *filter;
3890 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003891 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003892
3893 if (! peer->afc[afi][safi])
3894 return BGP_ERR_PEER_INACTIVE;
3895
3896 if (direct != FILTER_IN && direct != FILTER_OUT)
3897 return BGP_ERR_INVALID_VALUE;
3898
3899 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3900 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3901
3902 filter = &peer->filter[afi][safi];
3903
3904 if (filter->aslist[direct].name)
3905 free (filter->aslist[direct].name);
3906 filter->aslist[direct].name = strdup (name);
3907 filter->aslist[direct].aslist = as_list_lookup (name);
3908
3909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3910 return 0;
3911
3912 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003913 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003914 {
3915 filter = &peer->filter[afi][safi];
3916
3917 if (! peer->af_group[afi][safi])
3918 continue;
3919
3920 if (filter->aslist[direct].name)
3921 free (filter->aslist[direct].name);
3922 filter->aslist[direct].name = strdup (name);
3923 filter->aslist[direct].aslist = as_list_lookup (name);
3924 }
3925 return 0;
3926}
3927
3928int
3929peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3930{
3931 struct bgp_filter *filter;
3932 struct bgp_filter *gfilter;
3933 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003934 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003935
3936 if (! peer->afc[afi][safi])
3937 return BGP_ERR_PEER_INACTIVE;
3938
hassob5f29602005-05-25 21:00:28 +00003939 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003940 return BGP_ERR_INVALID_VALUE;
3941
hassob5f29602005-05-25 21:00:28 +00003942 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003943 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3944
3945 filter = &peer->filter[afi][safi];
3946
3947 /* apply peer-group filter */
3948 if (peer->af_group[afi][safi])
3949 {
3950 gfilter = &peer->group->conf->filter[afi][safi];
3951
3952 if (gfilter->aslist[direct].name)
3953 {
3954 if (filter->aslist[direct].name)
3955 free (filter->aslist[direct].name);
3956 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3957 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3958 return 0;
3959 }
3960 }
3961
3962 if (filter->aslist[direct].name)
3963 free (filter->aslist[direct].name);
3964 filter->aslist[direct].name = NULL;
3965 filter->aslist[direct].aslist = NULL;
3966
3967 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3968 return 0;
3969
3970 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003971 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003972 {
3973 filter = &peer->filter[afi][safi];
3974
3975 if (! peer->af_group[afi][safi])
3976 continue;
3977
3978 if (filter->aslist[direct].name)
3979 free (filter->aslist[direct].name);
3980 filter->aslist[direct].name = NULL;
3981 filter->aslist[direct].aslist = NULL;
3982 }
3983
3984 return 0;
3985}
3986
paul94f2b392005-06-28 12:44:16 +00003987static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003988peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003989{
3990 afi_t afi;
3991 safi_t safi;
3992 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003993 struct listnode *mnode, *mnnode;
3994 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003995 struct bgp *bgp;
3996 struct peer *peer;
3997 struct peer_group *group;
3998 struct bgp_filter *filter;
3999
paul1eb8ef22005-04-07 07:30:20 +00004000 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004001 {
paul1eb8ef22005-04-07 07:30:20 +00004002 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004003 {
4004 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4005 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4006 {
4007 filter = &peer->filter[afi][safi];
4008
4009 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4010 {
4011 if (filter->aslist[direct].name)
4012 filter->aslist[direct].aslist =
4013 as_list_lookup (filter->aslist[direct].name);
4014 else
4015 filter->aslist[direct].aslist = NULL;
4016 }
4017 }
4018 }
paul1eb8ef22005-04-07 07:30:20 +00004019 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004020 {
4021 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4022 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4023 {
4024 filter = &group->conf->filter[afi][safi];
4025
4026 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4027 {
4028 if (filter->aslist[direct].name)
4029 filter->aslist[direct].aslist =
4030 as_list_lookup (filter->aslist[direct].name);
4031 else
4032 filter->aslist[direct].aslist = NULL;
4033 }
4034 }
4035 }
4036 }
4037}
4038
4039/* Set route-map to the peer. */
4040int
4041peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004042 const char *name)
paul718e3742002-12-13 20:15:29 +00004043{
4044 struct bgp_filter *filter;
4045 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004046 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004047
4048 if (! peer->afc[afi][safi])
4049 return BGP_ERR_PEER_INACTIVE;
4050
paulfee0f4c2004-09-13 05:12:46 +00004051 if (direct != RMAP_IN && direct != RMAP_OUT &&
4052 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004053 return BGP_ERR_INVALID_VALUE;
4054
paulfee0f4c2004-09-13 05:12:46 +00004055 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4056 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004057 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4058
4059 filter = &peer->filter[afi][safi];
4060
4061 if (filter->map[direct].name)
4062 free (filter->map[direct].name);
4063
4064 filter->map[direct].name = strdup (name);
4065 filter->map[direct].map = route_map_lookup_by_name (name);
4066
4067 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4068 return 0;
4069
4070 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004071 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004072 {
4073 filter = &peer->filter[afi][safi];
4074
4075 if (! peer->af_group[afi][safi])
4076 continue;
4077
4078 if (filter->map[direct].name)
4079 free (filter->map[direct].name);
4080 filter->map[direct].name = strdup (name);
4081 filter->map[direct].map = route_map_lookup_by_name (name);
4082 }
4083 return 0;
4084}
4085
4086/* Unset route-map from the peer. */
4087int
4088peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4089{
4090 struct bgp_filter *filter;
4091 struct bgp_filter *gfilter;
4092 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004093 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004094
4095 if (! peer->afc[afi][safi])
4096 return BGP_ERR_PEER_INACTIVE;
4097
hassob5f29602005-05-25 21:00:28 +00004098 if (direct != RMAP_IN && direct != RMAP_OUT &&
4099 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004100 return BGP_ERR_INVALID_VALUE;
4101
hassob5f29602005-05-25 21:00:28 +00004102 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4103 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004104 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4105
4106 filter = &peer->filter[afi][safi];
4107
4108 /* apply peer-group filter */
4109 if (peer->af_group[afi][safi])
4110 {
4111 gfilter = &peer->group->conf->filter[afi][safi];
4112
4113 if (gfilter->map[direct].name)
4114 {
4115 if (filter->map[direct].name)
4116 free (filter->map[direct].name);
4117 filter->map[direct].name = strdup (gfilter->map[direct].name);
4118 filter->map[direct].map = gfilter->map[direct].map;
4119 return 0;
4120 }
4121 }
4122
4123 if (filter->map[direct].name)
4124 free (filter->map[direct].name);
4125 filter->map[direct].name = NULL;
4126 filter->map[direct].map = NULL;
4127
4128 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4129 return 0;
4130
4131 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004132 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004133 {
4134 filter = &peer->filter[afi][safi];
4135
4136 if (! peer->af_group[afi][safi])
4137 continue;
4138
4139 if (filter->map[direct].name)
4140 free (filter->map[direct].name);
4141 filter->map[direct].name = NULL;
4142 filter->map[direct].map = NULL;
4143 }
4144 return 0;
4145}
4146
4147/* Set unsuppress-map to the peer. */
4148int
paulfd79ac92004-10-13 05:06:08 +00004149peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4150 const char *name)
paul718e3742002-12-13 20:15:29 +00004151{
4152 struct bgp_filter *filter;
4153 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004155
4156 if (! peer->afc[afi][safi])
4157 return BGP_ERR_PEER_INACTIVE;
4158
4159 if (peer_is_group_member (peer, afi, safi))
4160 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4161
4162 filter = &peer->filter[afi][safi];
4163
4164 if (filter->usmap.name)
4165 free (filter->usmap.name);
4166
4167 filter->usmap.name = strdup (name);
4168 filter->usmap.map = route_map_lookup_by_name (name);
4169
4170 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4171 return 0;
4172
4173 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004174 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004175 {
4176 filter = &peer->filter[afi][safi];
4177
4178 if (! peer->af_group[afi][safi])
4179 continue;
4180
4181 if (filter->usmap.name)
4182 free (filter->usmap.name);
4183 filter->usmap.name = strdup (name);
4184 filter->usmap.map = route_map_lookup_by_name (name);
4185 }
4186 return 0;
4187}
4188
4189/* Unset route-map from the peer. */
4190int
4191peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4192{
4193 struct bgp_filter *filter;
4194 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004195 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004196
4197 if (! peer->afc[afi][safi])
4198 return BGP_ERR_PEER_INACTIVE;
4199
4200 if (peer_is_group_member (peer, afi, safi))
4201 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4202
4203 filter = &peer->filter[afi][safi];
4204
4205 if (filter->usmap.name)
4206 free (filter->usmap.name);
4207 filter->usmap.name = NULL;
4208 filter->usmap.map = NULL;
4209
4210 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4211 return 0;
4212
4213 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004214 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004215 {
4216 filter = &peer->filter[afi][safi];
4217
4218 if (! peer->af_group[afi][safi])
4219 continue;
4220
4221 if (filter->usmap.name)
4222 free (filter->usmap.name);
4223 filter->usmap.name = NULL;
4224 filter->usmap.map = NULL;
4225 }
4226 return 0;
4227}
4228
4229int
4230peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004231 u_int32_t max, u_char threshold,
4232 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004233{
4234 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004235 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004236
4237 if (! peer->afc[afi][safi])
4238 return BGP_ERR_PEER_INACTIVE;
4239
4240 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4241 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004242 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004243 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004244 if (warning)
4245 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4246 else
4247 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4248
4249 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4250 return 0;
4251
4252 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004253 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004254 {
4255 if (! peer->af_group[afi][safi])
4256 continue;
4257
4258 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4259 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004260 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004261 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004262 if (warning)
4263 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4264 else
4265 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4266 }
4267 return 0;
4268}
4269
4270int
4271peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4272{
4273 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004274 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004275
4276 if (! peer->afc[afi][safi])
4277 return BGP_ERR_PEER_INACTIVE;
4278
4279 /* apply peer-group config */
4280 if (peer->af_group[afi][safi])
4281 {
4282 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4283 PEER_FLAG_MAX_PREFIX))
4284 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4285 else
4286 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4287
4288 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4289 PEER_FLAG_MAX_PREFIX_WARNING))
4290 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4291 else
4292 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4293
4294 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004295 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004296 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004297 return 0;
4298 }
4299
4300 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4301 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4302 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004303 peer->pmax_threshold[afi][safi] = 0;
4304 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004305
4306 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4307 return 0;
4308
4309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004311 {
4312 if (! peer->af_group[afi][safi])
4313 continue;
4314
4315 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4316 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4317 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004318 peer->pmax_threshold[afi][safi] = 0;
4319 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004320 }
4321 return 0;
4322}
4323
4324int
4325peer_clear (struct peer *peer)
4326{
4327 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4328 {
hasso0a486e52005-02-01 20:57:17 +00004329 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4330 {
4331 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4332 if (peer->t_pmax_restart)
4333 {
4334 BGP_TIMER_OFF (peer->t_pmax_restart);
4335 if (BGP_DEBUG (events, EVENTS))
4336 zlog_debug ("%s Maximum-prefix restart timer canceled",
4337 peer->host);
4338 }
4339 BGP_EVENT_ADD (peer, BGP_Start);
4340 return 0;
4341 }
4342
paul718e3742002-12-13 20:15:29 +00004343 peer->v_start = BGP_INIT_START_TIMER;
4344 if (peer->status == Established)
4345 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4346 BGP_NOTIFY_CEASE_ADMIN_RESET);
4347 else
4348 BGP_EVENT_ADD (peer, BGP_Stop);
4349 }
4350 return 0;
4351}
4352
4353int
4354peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4355 enum bgp_clear_type stype)
4356{
4357 if (peer->status != Established)
4358 return 0;
4359
4360 if (! peer->afc[afi][safi])
4361 return BGP_ERR_AF_UNCONFIGURED;
4362
paulfee0f4c2004-09-13 05:12:46 +00004363 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4364 {
4365 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4366 return 0;
4367 bgp_check_local_routes_rsclient (peer, afi, safi);
4368 bgp_soft_reconfig_rsclient (peer, afi, safi);
4369 }
4370
paul718e3742002-12-13 20:15:29 +00004371 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4372 bgp_announce_route (peer, afi, safi);
4373
4374 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4375 {
4376 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4377 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4378 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4379 {
4380 struct bgp_filter *filter = &peer->filter[afi][safi];
4381 u_char prefix_type;
4382
4383 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4384 prefix_type = ORF_TYPE_PREFIX;
4385 else
4386 prefix_type = ORF_TYPE_PREFIX_OLD;
4387
4388 if (filter->plist[FILTER_IN].plist)
4389 {
4390 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4391 bgp_route_refresh_send (peer, afi, safi,
4392 prefix_type, REFRESH_DEFER, 1);
4393 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4394 REFRESH_IMMEDIATE, 0);
4395 }
4396 else
4397 {
4398 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4399 bgp_route_refresh_send (peer, afi, safi,
4400 prefix_type, REFRESH_IMMEDIATE, 1);
4401 else
4402 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4403 }
4404 return 0;
4405 }
4406 }
4407
4408 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4409 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4410 {
4411 /* If neighbor has soft reconfiguration inbound flag.
4412 Use Adj-RIB-In database. */
4413 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4414 bgp_soft_reconfig_in (peer, afi, safi);
4415 else
4416 {
4417 /* If neighbor has route refresh capability, send route refresh
4418 message to the peer. */
4419 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4420 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4421 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4422 else
4423 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4424 }
4425 }
4426 return 0;
4427}
4428
paulfd79ac92004-10-13 05:06:08 +00004429/* Display peer uptime.*/
4430/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004431char *
4432peer_uptime (time_t uptime2, char *buf, size_t len)
4433{
4434 time_t uptime1;
4435 struct tm *tm;
4436
4437 /* Check buffer length. */
4438 if (len < BGP_UPTIME_LEN)
4439 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004440 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004441 /* XXX: should return status instead of buf... */
4442 snprintf (buf, len, "<error> ");
4443 return buf;
paul718e3742002-12-13 20:15:29 +00004444 }
4445
4446 /* If there is no connection has been done before print `never'. */
4447 if (uptime2 == 0)
4448 {
4449 snprintf (buf, len, "never ");
4450 return buf;
4451 }
4452
4453 /* Get current time. */
4454 uptime1 = time (NULL);
4455 uptime1 -= uptime2;
4456 tm = gmtime (&uptime1);
4457
4458 /* Making formatted timer strings. */
4459#define ONE_DAY_SECOND 60*60*24
4460#define ONE_WEEK_SECOND 60*60*24*7
4461
4462 if (uptime1 < ONE_DAY_SECOND)
4463 snprintf (buf, len, "%02d:%02d:%02d",
4464 tm->tm_hour, tm->tm_min, tm->tm_sec);
4465 else if (uptime1 < ONE_WEEK_SECOND)
4466 snprintf (buf, len, "%dd%02dh%02dm",
4467 tm->tm_yday, tm->tm_hour, tm->tm_min);
4468 else
4469 snprintf (buf, len, "%02dw%dd%02dh",
4470 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4471 return buf;
4472}
4473
paul94f2b392005-06-28 12:44:16 +00004474static void
paul718e3742002-12-13 20:15:29 +00004475bgp_config_write_filter (struct vty *vty, struct peer *peer,
4476 afi_t afi, safi_t safi)
4477{
4478 struct bgp_filter *filter;
4479 struct bgp_filter *gfilter = NULL;
4480 char *addr;
4481 int in = FILTER_IN;
4482 int out = FILTER_OUT;
4483
4484 addr = peer->host;
4485 filter = &peer->filter[afi][safi];
4486 if (peer->af_group[afi][safi])
4487 gfilter = &peer->group->conf->filter[afi][safi];
4488
4489 /* distribute-list. */
4490 if (filter->dlist[in].name)
4491 if (! gfilter || ! gfilter->dlist[in].name
4492 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4493 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4494 filter->dlist[in].name, VTY_NEWLINE);
4495 if (filter->dlist[out].name && ! gfilter)
4496 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4497 filter->dlist[out].name, VTY_NEWLINE);
4498
4499 /* prefix-list. */
4500 if (filter->plist[in].name)
4501 if (! gfilter || ! gfilter->plist[in].name
4502 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4503 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4504 filter->plist[in].name, VTY_NEWLINE);
4505 if (filter->plist[out].name && ! gfilter)
4506 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4507 filter->plist[out].name, VTY_NEWLINE);
4508
4509 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004510 if (filter->map[RMAP_IN].name)
4511 if (! gfilter || ! gfilter->map[RMAP_IN].name
4512 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004513 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004514 filter->map[RMAP_IN].name, VTY_NEWLINE);
4515 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004516 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004517 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4518 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4519 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4520 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4521 if (filter->map[RMAP_EXPORT].name)
4522 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4523 || strcmp (filter->map[RMAP_EXPORT].name,
4524 gfilter->map[RMAP_EXPORT].name) != 0)
4525 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4526 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004527
4528 /* unsuppress-map */
4529 if (filter->usmap.name && ! gfilter)
4530 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4531 filter->usmap.name, VTY_NEWLINE);
4532
4533 /* filter-list. */
4534 if (filter->aslist[in].name)
4535 if (! gfilter || ! gfilter->aslist[in].name
4536 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4537 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4538 filter->aslist[in].name, VTY_NEWLINE);
4539 if (filter->aslist[out].name && ! gfilter)
4540 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4541 filter->aslist[out].name, VTY_NEWLINE);
4542}
4543
4544/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004545static void
paul718e3742002-12-13 20:15:29 +00004546bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4547 struct peer *peer, afi_t afi, safi_t safi)
4548{
4549 struct bgp_filter *filter;
4550 struct peer *g_peer = NULL;
4551 char buf[SU_ADDRSTRLEN];
4552 char *addr;
4553
4554 filter = &peer->filter[afi][safi];
4555 addr = peer->host;
4556 if (peer_group_active (peer))
4557 g_peer = peer->group->conf;
4558
4559 /************************************
4560 ****** Global to the neighbor ******
4561 ************************************/
4562 if (afi == AFI_IP && safi == SAFI_UNICAST)
4563 {
4564 /* remote-as. */
4565 if (! peer_group_active (peer))
4566 {
4567 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4568 vty_out (vty, " neighbor %s peer-group%s", addr,
4569 VTY_NEWLINE);
4570 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004571 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004572 VTY_NEWLINE);
4573 }
4574 else
4575 {
4576 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004577 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004578 VTY_NEWLINE);
4579 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4580 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4581 peer->group->name, VTY_NEWLINE);
4582 }
4583
4584 /* local-as. */
4585 if (peer->change_local_as)
4586 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004587 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004588 peer->change_local_as,
4589 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4590 " no-prepend" : "", VTY_NEWLINE);
4591
4592 /* Description. */
4593 if (peer->desc)
4594 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4595 VTY_NEWLINE);
4596
4597 /* Shutdown. */
4598 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4599 if (! peer_group_active (peer) ||
4600 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4601 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4602
Paul Jakma0df7c912008-07-21 21:02:49 +00004603 /* Password. */
4604 if (peer->password)
4605 if (!peer_group_active (peer)
4606 || ! g_peer->password
4607 || strcmp (peer->password, g_peer->password) != 0)
4608 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4609 VTY_NEWLINE);
4610
paul718e3742002-12-13 20:15:29 +00004611 /* BGP port. */
4612 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004613 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004614 VTY_NEWLINE);
4615
4616 /* Local interface name. */
4617 if (peer->ifname)
4618 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4619 VTY_NEWLINE);
4620
4621 /* Passive. */
4622 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4623 if (! peer_group_active (peer) ||
4624 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4625 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4626
4627 /* EBGP multihop. */
4628 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4629 if (! peer_group_active (peer) ||
4630 g_peer->ttl != peer->ttl)
4631 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4632 VTY_NEWLINE);
4633
hasso6ffd2072005-02-02 14:50:11 +00004634 /* disable-connected-check. */
4635 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004636 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004637 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4638 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004639
4640 /* Update-source. */
4641 if (peer->update_if)
4642 if (! peer_group_active (peer) || ! g_peer->update_if
4643 || strcmp (g_peer->update_if, peer->update_if) != 0)
4644 vty_out (vty, " neighbor %s update-source %s%s", addr,
4645 peer->update_if, VTY_NEWLINE);
4646 if (peer->update_source)
4647 if (! peer_group_active (peer) || ! g_peer->update_source
4648 || sockunion_cmp (g_peer->update_source,
4649 peer->update_source) != 0)
4650 vty_out (vty, " neighbor %s update-source %s%s", addr,
4651 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4652 VTY_NEWLINE);
4653
paul718e3742002-12-13 20:15:29 +00004654 /* advertisement-interval */
4655 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4656 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4657 addr, peer->v_routeadv, VTY_NEWLINE);
4658
4659 /* timers. */
4660 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4661 && ! peer_group_active (peer))
4662 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4663 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4664
4665 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4666 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4667 peer->connect, VTY_NEWLINE);
4668
4669 /* Default weight. */
4670 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4671 if (! peer_group_active (peer) ||
4672 g_peer->weight != peer->weight)
4673 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4674 VTY_NEWLINE);
4675
paul718e3742002-12-13 20:15:29 +00004676 /* Dynamic capability. */
4677 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4678 if (! peer_group_active (peer) ||
4679 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4680 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4681 VTY_NEWLINE);
4682
4683 /* dont capability negotiation. */
4684 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4685 if (! peer_group_active (peer) ||
4686 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4687 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4688 VTY_NEWLINE);
4689
4690 /* override capability negotiation. */
4691 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4692 if (! peer_group_active (peer) ||
4693 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4694 vty_out (vty, " neighbor %s override-capability%s", addr,
4695 VTY_NEWLINE);
4696
4697 /* strict capability negotiation. */
4698 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4699 if (! peer_group_active (peer) ||
4700 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4701 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4702 VTY_NEWLINE);
4703
4704 if (! peer_group_active (peer))
4705 {
4706 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4707 {
4708 if (peer->afc[AFI_IP][SAFI_UNICAST])
4709 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4710 }
4711 else
4712 {
4713 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4714 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4715 }
4716 }
4717 }
4718
4719
4720 /************************************
4721 ****** Per AF to the neighbor ******
4722 ************************************/
4723
4724 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4725 {
4726 if (peer->af_group[afi][safi])
4727 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4728 peer->group->name, VTY_NEWLINE);
4729 else
4730 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4731 }
4732
4733 /* ORF capability. */
4734 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4735 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4736 if (! peer->af_group[afi][safi])
4737 {
4738 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4739
4740 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4741 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4742 vty_out (vty, " both");
4743 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4744 vty_out (vty, " send");
4745 else
4746 vty_out (vty, " receive");
4747 vty_out (vty, "%s", VTY_NEWLINE);
4748 }
4749
4750 /* Route reflector client. */
4751 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4752 && ! peer->af_group[afi][safi])
4753 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4754 VTY_NEWLINE);
4755
4756 /* Nexthop self. */
4757 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4758 && ! peer->af_group[afi][safi])
4759 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4760
4761 /* Remove private AS. */
4762 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4763 && ! peer->af_group[afi][safi])
4764 vty_out (vty, " neighbor %s remove-private-AS%s",
4765 addr, VTY_NEWLINE);
4766
4767 /* send-community print. */
4768 if (! peer->af_group[afi][safi])
4769 {
4770 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4771 {
4772 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4773 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4774 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4775 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4776 vty_out (vty, " neighbor %s send-community extended%s",
4777 addr, VTY_NEWLINE);
4778 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4779 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4780 }
4781 else
4782 {
4783 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4784 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4785 vty_out (vty, " no neighbor %s send-community both%s",
4786 addr, VTY_NEWLINE);
4787 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4788 vty_out (vty, " no neighbor %s send-community extended%s",
4789 addr, VTY_NEWLINE);
4790 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4791 vty_out (vty, " no neighbor %s send-community%s",
4792 addr, VTY_NEWLINE);
4793 }
4794 }
4795
4796 /* Default information */
4797 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4798 && ! peer->af_group[afi][safi])
4799 {
4800 vty_out (vty, " neighbor %s default-originate", addr);
4801 if (peer->default_rmap[afi][safi].name)
4802 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4803 vty_out (vty, "%s", VTY_NEWLINE);
4804 }
4805
4806 /* Soft reconfiguration inbound. */
4807 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4808 if (! peer->af_group[afi][safi] ||
4809 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4810 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4811 VTY_NEWLINE);
4812
4813 /* maximum-prefix. */
4814 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4815 if (! peer->af_group[afi][safi]
4816 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004817 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004818 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4819 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004820 {
hasso0a486e52005-02-01 20:57:17 +00004821 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4822 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4823 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4824 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4825 vty_out (vty, " warning-only");
4826 if (peer->pmax_restart[afi][safi])
4827 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4828 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004829 }
paul718e3742002-12-13 20:15:29 +00004830
4831 /* Route server client. */
4832 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4833 && ! peer->af_group[afi][safi])
4834 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4835
4836 /* Allow AS in. */
4837 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4838 if (! peer_group_active (peer)
4839 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4840 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4841 {
4842 if (peer->allowas_in[afi][safi] == 3)
4843 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4844 else
4845 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4846 peer->allowas_in[afi][safi], VTY_NEWLINE);
4847 }
4848
4849 /* Filter. */
4850 bgp_config_write_filter (vty, peer, afi, safi);
4851
4852 /* atribute-unchanged. */
4853 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4854 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4855 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4856 && ! peer->af_group[afi][safi])
4857 {
4858 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4859 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4860 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4861 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4862 else
4863 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4864 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4865 " as-path" : "",
4866 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4867 " next-hop" : "",
4868 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4869 " med" : "", VTY_NEWLINE);
4870 }
4871}
4872
4873/* Display "address-family" configuration header. */
4874void
4875bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4876 int *write)
4877{
4878 if (*write)
4879 return;
4880
4881 if (afi == AFI_IP && safi == SAFI_UNICAST)
4882 return;
4883
4884 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4885
4886 if (afi == AFI_IP)
4887 {
4888 if (safi == SAFI_MULTICAST)
4889 vty_out (vty, "ipv4 multicast");
4890 else if (safi == SAFI_MPLS_VPN)
4891 vty_out (vty, "vpnv4 unicast");
4892 }
4893 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004894 {
4895 vty_out (vty, "ipv6");
4896
4897 if (safi == SAFI_MULTICAST)
4898 vty_out (vty, " multicast");
4899 }
paul718e3742002-12-13 20:15:29 +00004900
4901 vty_out (vty, "%s", VTY_NEWLINE);
4902
4903 *write = 1;
4904}
4905
4906/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004907static int
paul718e3742002-12-13 20:15:29 +00004908bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4909 safi_t safi)
4910{
4911 int write = 0;
4912 struct peer *peer;
4913 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004915
4916 bgp_config_write_network (vty, bgp, afi, safi, &write);
4917
4918 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4919
paul1eb8ef22005-04-07 07:30:20 +00004920 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004921 {
4922 if (group->conf->afc[afi][safi])
4923 {
4924 bgp_config_write_family_header (vty, afi, safi, &write);
4925 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4926 }
4927 }
paul1eb8ef22005-04-07 07:30:20 +00004928 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004929 {
4930 if (peer->afc[afi][safi])
4931 {
4932 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4933 {
4934 bgp_config_write_family_header (vty, afi, safi, &write);
4935 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4936 }
4937 }
4938 }
4939 if (write)
4940 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4941
4942 return write;
4943}
4944
4945int
4946bgp_config_write (struct vty *vty)
4947{
4948 int write = 0;
4949 struct bgp *bgp;
4950 struct peer_group *group;
4951 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004952 struct listnode *node, *nnode;
4953 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004954
4955 /* BGP Multiple instance. */
4956 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4957 {
4958 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4959 write++;
4960 }
4961
4962 /* BGP Config type. */
4963 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4964 {
4965 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4966 write++;
4967 }
4968
4969 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004970 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004971 {
4972 if (write)
4973 vty_out (vty, "!%s", VTY_NEWLINE);
4974
4975 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004976 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004977
4978 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4979 {
4980 if (bgp->name)
4981 vty_out (vty, " view %s", bgp->name);
4982 }
4983 vty_out (vty, "%s", VTY_NEWLINE);
4984
4985 /* No Synchronization */
4986 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4987 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4988
4989 /* BGP fast-external-failover. */
4990 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4991 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4992
4993 /* BGP router ID. */
4994 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4995 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4996 VTY_NEWLINE);
4997
paul848973c2003-08-13 00:32:49 +00004998 /* BGP log-neighbor-changes. */
4999 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5000 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5001
paul718e3742002-12-13 20:15:29 +00005002 /* BGP configuration. */
5003 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5004 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5005
5006 /* BGP default ipv4-unicast. */
5007 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5008 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5009
5010 /* BGP default local-preference. */
5011 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5012 vty_out (vty, " bgp default local-preference %d%s",
5013 bgp->default_local_pref, VTY_NEWLINE);
5014
5015 /* BGP client-to-client reflection. */
5016 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5017 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5018
5019 /* BGP cluster ID. */
5020 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5021 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5022 VTY_NEWLINE);
5023
hassoe0701b72004-05-20 09:19:34 +00005024 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005025 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005026 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5027 VTY_NEWLINE);
5028
5029 /* Confederation peer */
5030 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005031 {
hassoe0701b72004-05-20 09:19:34 +00005032 int i;
paul718e3742002-12-13 20:15:29 +00005033
hassoe0701b72004-05-20 09:19:34 +00005034 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005035
hassoe0701b72004-05-20 09:19:34 +00005036 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005037 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005038
hassoe0701b72004-05-20 09:19:34 +00005039 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005040 }
5041
5042 /* BGP enforce-first-as. */
5043 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5044 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5045
5046 /* BGP deterministic-med. */
5047 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5048 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005049
5050 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005051 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5052 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5053 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005054 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5055 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5056
paul718e3742002-12-13 20:15:29 +00005057 /* BGP bestpath method. */
5058 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5059 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005060 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5061 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005062 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5063 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5064 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5065 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5066 {
5067 vty_out (vty, " bgp bestpath med");
5068 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5069 vty_out (vty, " confed");
5070 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5071 vty_out (vty, " missing-as-worst");
5072 vty_out (vty, "%s", VTY_NEWLINE);
5073 }
5074
5075 /* BGP network import check. */
5076 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5077 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5078
5079 /* BGP scan interval. */
5080 bgp_config_write_scan_time (vty);
5081
5082 /* BGP flag dampening. */
5083 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5084 BGP_CONFIG_DAMPENING))
5085 bgp_config_write_damp (vty);
5086
5087 /* BGP static route configuration. */
5088 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5089
5090 /* BGP redistribute configuration. */
5091 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5092
5093 /* BGP timers configuration. */
5094 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5095 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5096 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5097 bgp->default_holdtime, VTY_NEWLINE);
5098
5099 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005100 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005101 {
5102 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5103 }
5104
5105 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005106 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005107 {
5108 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5109 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5110 }
5111
5112 /* Distance configuration. */
5113 bgp_config_write_distance (vty, bgp);
5114
5115 /* No auto-summary */
5116 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5117 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5118
5119 /* IPv4 multicast configuration. */
5120 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5121
5122 /* IPv4 VPN configuration. */
5123 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5124
5125 /* IPv6 unicast configuration. */
5126 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5127
Paul Jakma37a217a2007-04-10 19:20:29 +00005128 /* IPv6 multicast configuration. */
5129 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5130
paul718e3742002-12-13 20:15:29 +00005131 write++;
5132 }
5133 return write;
5134}
5135
5136void
paul94f2b392005-06-28 12:44:16 +00005137bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005138{
5139 memset (&bgp_master, 0, sizeof (struct bgp_master));
5140
5141 bm = &bgp_master;
5142 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005143 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005144 bm->port = BGP_PORT_DEFAULT;
5145 bm->master = thread_master_create ();
5146 bm->start_time = time (NULL);
5147}
paul200df112005-06-01 11:17:05 +00005148
paul718e3742002-12-13 20:15:29 +00005149
5150void
paul94f2b392005-06-28 12:44:16 +00005151bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005152{
paul718e3742002-12-13 20:15:29 +00005153 /* BGP VTY commands installation. */
5154 bgp_vty_init ();
5155
paul718e3742002-12-13 20:15:29 +00005156 /* Init zebra. */
5157 bgp_zebra_init ();
5158
5159 /* BGP inits. */
5160 bgp_attr_init ();
5161 bgp_debug_init ();
5162 bgp_dump_init ();
5163 bgp_route_init ();
5164 bgp_route_map_init ();
5165 bgp_scan_init ();
5166 bgp_mplsvpn_init ();
5167
5168 /* Access list initialize. */
5169 access_list_init ();
5170 access_list_add_hook (peer_distribute_update);
5171 access_list_delete_hook (peer_distribute_update);
5172
5173 /* Filter list initialize. */
5174 bgp_filter_init ();
5175 as_list_add_hook (peer_aslist_update);
5176 as_list_delete_hook (peer_aslist_update);
5177
5178 /* Prefix list initialize.*/
5179 prefix_list_init ();
5180 prefix_list_add_hook (peer_prefix_list_update);
5181 prefix_list_delete_hook (peer_prefix_list_update);
5182
5183 /* Community list initialize. */
5184 bgp_clist = community_list_init ();
5185
5186#ifdef HAVE_SNMP
5187 bgp_snmp_init ();
5188#endif /* HAVE_SNMP */
5189}
paul545acaf2004-04-20 15:13:15 +00005190
5191void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005192bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005193{
paul545acaf2004-04-20 15:13:15 +00005194 struct bgp *bgp;
5195 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005196 struct listnode *node, *nnode;
5197 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005198
paul1eb8ef22005-04-07 07:30:20 +00005199 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5200 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005201 if (peer->status == Established)
5202 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5203 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005204
paul545acaf2004-04-20 15:13:15 +00005205 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005206
paule210cf92005-06-15 19:15:35 +00005207 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005208 {
5209 work_queue_free (bm->process_main_queue);
5210 bm->process_main_queue = NULL;
5211 }
paule210cf92005-06-15 19:15:35 +00005212 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005213 {
5214 work_queue_free (bm->process_rsclient_queue);
5215 bm->process_rsclient_queue = NULL;
5216 }
paul545acaf2004-04-20 15:13:15 +00005217}