blob: cf3a6b424094f878a9b6b998104caf859bed1090 [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
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001132static void
hasso93406d82005-02-02 14:40:33 +00001133peer_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;
Paul Jakma9d878772009-08-05 16:25:16 +01002172 struct listnode *node;
2173 struct listnode *bgpnode;
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 Jakma9d878772009-08-05 16:25:16 +01002179 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002180 {
Paul Jakma9d878772009-08-05 16:25:16 +01002181 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2182 {
2183 if (sockunion_same (&peer->su, su)
2184 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2185 {
2186 if (peer->as == remote_as
2187 && peer->remote_id.s_addr == remote_id->s_addr)
2188 return peer;
2189 if (peer->as == remote_as)
2190 *as = 1;
2191 }
2192 }
2193
2194 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2195 {
2196 if (sockunion_same (&peer->su, su)
2197 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2198 {
2199 if (peer->as == remote_as
2200 && peer->remote_id.s_addr == 0)
2201 return peer;
2202 if (peer->as == remote_as)
2203 *as = 1;
2204 }
2205 }
paul718e3742002-12-13 20:15:29 +00002206 }
2207 return NULL;
2208}
2209
2210/* If peer is configured at least one address family return 1. */
2211int
2212peer_active (struct peer *peer)
2213{
2214 if (peer->afc[AFI_IP][SAFI_UNICAST]
2215 || peer->afc[AFI_IP][SAFI_MULTICAST]
2216 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2217 || peer->afc[AFI_IP6][SAFI_UNICAST]
2218 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2219 return 1;
2220 return 0;
2221}
2222
2223/* If peer is negotiated at least one address family return 1. */
2224int
2225peer_active_nego (struct peer *peer)
2226{
2227 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2228 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2229 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2230 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2231 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2232 return 1;
2233 return 0;
2234}
2235
2236/* peer_flag_change_type. */
2237enum peer_change_type
2238{
2239 peer_change_none,
2240 peer_change_reset,
2241 peer_change_reset_in,
2242 peer_change_reset_out,
2243};
2244
paul94f2b392005-06-28 12:44:16 +00002245static void
paul718e3742002-12-13 20:15:29 +00002246peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2247 enum peer_change_type type)
2248{
2249 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2250 return;
2251
2252 if (type == peer_change_reset)
2253 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2254 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2255 else if (type == peer_change_reset_in)
2256 {
2257 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2258 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2259 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2260 else
2261 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2262 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2263 }
2264 else if (type == peer_change_reset_out)
2265 bgp_announce_route (peer, afi, safi);
2266}
2267
2268struct peer_flag_action
2269{
2270 /* Peer's flag. */
2271 u_int32_t flag;
2272
2273 /* This flag can be set for peer-group member. */
2274 u_char not_for_member;
2275
2276 /* Action when the flag is changed. */
2277 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002278
2279 /* Peer down cause */
2280 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002281};
2282
Stephen Hemminger03621952009-07-21 16:27:20 -07002283static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002284 {
2285 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2286 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2287 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2288 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2289 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002290 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002291 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002292 { 0, 0, 0 }
2293 };
2294
Stephen Hemminger03621952009-07-21 16:27:20 -07002295static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002296 {
2297 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2298 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2299 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2300 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2301 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2302 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2303 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2304 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2305 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2306 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2307 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2308 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2309 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002310 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002311 { 0, 0, 0 }
2312 };
2313
2314/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002315static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002316peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002317 struct peer_flag_action *action, u_int32_t flag)
2318{
2319 int i;
2320 int found = 0;
2321 int reset_in = 0;
2322 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002323 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002324
2325 /* Check peer's frag action. */
2326 for (i = 0; i < size; i++)
2327 {
2328 match = &action_list[i];
2329
2330 if (match->flag == 0)
2331 break;
2332
2333 if (match->flag & flag)
2334 {
2335 found = 1;
2336
2337 if (match->type == peer_change_reset_in)
2338 reset_in = 1;
2339 if (match->type == peer_change_reset_out)
2340 reset_out = 1;
2341 if (match->type == peer_change_reset)
2342 {
2343 reset_in = 1;
2344 reset_out = 1;
2345 }
2346 if (match->not_for_member)
2347 action->not_for_member = 1;
2348 }
2349 }
2350
2351 /* Set peer clear type. */
2352 if (reset_in && reset_out)
2353 action->type = peer_change_reset;
2354 else if (reset_in)
2355 action->type = peer_change_reset_in;
2356 else if (reset_out)
2357 action->type = peer_change_reset_out;
2358 else
2359 action->type = peer_change_none;
2360
2361 return found;
2362}
2363
paul94f2b392005-06-28 12:44:16 +00002364static void
paul718e3742002-12-13 20:15:29 +00002365peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2366{
2367 if (flag == PEER_FLAG_SHUTDOWN)
2368 {
2369 if (CHECK_FLAG (peer->flags, flag))
2370 {
hasso93406d82005-02-02 14:40:33 +00002371 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2372 peer_nsf_stop (peer);
2373
hasso0a486e52005-02-01 20:57:17 +00002374 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2375 if (peer->t_pmax_restart)
2376 {
2377 BGP_TIMER_OFF (peer->t_pmax_restart);
2378 if (BGP_DEBUG (events, EVENTS))
2379 zlog_debug ("%s Maximum-prefix restart timer canceled",
2380 peer->host);
2381 }
2382
hasso93406d82005-02-02 14:40:33 +00002383 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2384 peer_nsf_stop (peer);
2385
paul718e3742002-12-13 20:15:29 +00002386 if (peer->status == Established)
2387 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2388 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2389 else
2390 BGP_EVENT_ADD (peer, BGP_Stop);
2391 }
2392 else
2393 {
2394 peer->v_start = BGP_INIT_START_TIMER;
2395 BGP_EVENT_ADD (peer, BGP_Stop);
2396 }
2397 }
2398 else if (peer->status == Established)
2399 {
hassoc9502432005-02-01 22:01:48 +00002400 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2401 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2402 else if (flag == PEER_FLAG_PASSIVE)
2403 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002404 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002405 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002406
hassoc9502432005-02-01 22:01:48 +00002407 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2408 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002409 }
2410 else
2411 BGP_EVENT_ADD (peer, BGP_Stop);
2412}
2413
2414/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002415static int
paul718e3742002-12-13 20:15:29 +00002416peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2417{
2418 int found;
2419 int size;
2420 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002421 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002422 struct peer_flag_action action;
2423
2424 memset (&action, 0, sizeof (struct peer_flag_action));
2425 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2426
2427 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2428
2429 /* No flag action is found. */
2430 if (! found)
2431 return BGP_ERR_INVALID_FLAG;
2432
2433 /* Not for peer-group member. */
2434 if (action.not_for_member && peer_group_active (peer))
2435 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2436
2437 /* When unset the peer-group member's flag we have to check
2438 peer-group configuration. */
2439 if (! set && peer_group_active (peer))
2440 if (CHECK_FLAG (peer->group->conf->flags, flag))
2441 {
2442 if (flag == PEER_FLAG_SHUTDOWN)
2443 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2444 else
2445 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2446 }
2447
2448 /* Flag conflict check. */
2449 if (set
2450 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2451 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2452 return BGP_ERR_PEER_FLAG_CONFLICT;
2453
2454 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2455 {
2456 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2457 return 0;
2458 if (! set && ! CHECK_FLAG (peer->flags, flag))
2459 return 0;
2460 }
2461
2462 if (set)
2463 SET_FLAG (peer->flags, flag);
2464 else
2465 UNSET_FLAG (peer->flags, flag);
2466
2467 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2468 {
2469 if (action.type == peer_change_reset)
2470 peer_flag_modify_action (peer, flag);
2471
2472 return 0;
2473 }
2474
2475 /* peer-group member updates. */
2476 group = peer->group;
2477
paul1eb8ef22005-04-07 07:30:20 +00002478 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002479 {
2480 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2481 continue;
2482
2483 if (! set && ! CHECK_FLAG (peer->flags, flag))
2484 continue;
2485
2486 if (set)
2487 SET_FLAG (peer->flags, flag);
2488 else
2489 UNSET_FLAG (peer->flags, flag);
2490
2491 if (action.type == peer_change_reset)
2492 peer_flag_modify_action (peer, flag);
2493 }
2494 return 0;
2495}
2496
2497int
2498peer_flag_set (struct peer *peer, u_int32_t flag)
2499{
2500 return peer_flag_modify (peer, flag, 1);
2501}
2502
2503int
2504peer_flag_unset (struct peer *peer, u_int32_t flag)
2505{
2506 return peer_flag_modify (peer, flag, 0);
2507}
2508
paul94f2b392005-06-28 12:44:16 +00002509static int
paul718e3742002-12-13 20:15:29 +00002510peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2511{
2512 if (peer->af_group[afi][safi])
2513 return 1;
2514 return 0;
2515}
2516
paul94f2b392005-06-28 12:44:16 +00002517static int
paul718e3742002-12-13 20:15:29 +00002518peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2519 int set)
2520{
2521 int found;
2522 int size;
paul1eb8ef22005-04-07 07:30:20 +00002523 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002524 struct peer_group *group;
2525 struct peer_flag_action action;
2526
2527 memset (&action, 0, sizeof (struct peer_flag_action));
2528 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2529
2530 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2531
2532 /* No flag action is found. */
2533 if (! found)
2534 return BGP_ERR_INVALID_FLAG;
2535
2536 /* Adress family must be activated. */
2537 if (! peer->afc[afi][safi])
2538 return BGP_ERR_PEER_INACTIVE;
2539
2540 /* Not for peer-group member. */
2541 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2542 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2543
2544 /* Spcecial check for reflector client. */
2545 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2546 && peer_sort (peer) != BGP_PEER_IBGP)
2547 return BGP_ERR_NOT_INTERNAL_PEER;
2548
2549 /* Spcecial check for remove-private-AS. */
2550 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2551 && peer_sort (peer) == BGP_PEER_IBGP)
2552 return BGP_ERR_REMOVE_PRIVATE_AS;
2553
2554 /* When unset the peer-group member's flag we have to check
2555 peer-group configuration. */
2556 if (! set && peer->af_group[afi][safi])
2557 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2558 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2559
2560 /* When current flag configuration is same as requested one. */
2561 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2562 {
2563 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2564 return 0;
2565 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2566 return 0;
2567 }
2568
2569 if (set)
2570 SET_FLAG (peer->af_flags[afi][safi], flag);
2571 else
2572 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2573
2574 /* Execute action when peer is established. */
2575 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2576 && peer->status == Established)
2577 {
2578 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2579 bgp_clear_adj_in (peer, afi, safi);
2580 else
hassoe0701b72004-05-20 09:19:34 +00002581 {
2582 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2583 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2584 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2585 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2586 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2587 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2588 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2589 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2590
2591 peer_change_action (peer, afi, safi, action.type);
2592 }
2593
paul718e3742002-12-13 20:15:29 +00002594 }
2595
2596 /* Peer group member updates. */
2597 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2598 {
2599 group = peer->group;
2600
paul1eb8ef22005-04-07 07:30:20 +00002601 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002602 {
2603 if (! peer->af_group[afi][safi])
2604 continue;
2605
2606 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2607 continue;
2608
2609 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2610 continue;
2611
2612 if (set)
2613 SET_FLAG (peer->af_flags[afi][safi], flag);
2614 else
2615 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2616
2617 if (peer->status == Established)
2618 {
2619 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2620 bgp_clear_adj_in (peer, afi, safi);
2621 else
hassoe0701b72004-05-20 09:19:34 +00002622 {
2623 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2624 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2625 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2626 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2627 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2628 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2629 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2630 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2631
2632 peer_change_action (peer, afi, safi, action.type);
2633 }
paul718e3742002-12-13 20:15:29 +00002634 }
2635 }
2636 }
2637 return 0;
2638}
2639
2640int
2641peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2642{
2643 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2644}
2645
2646int
2647peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2648{
2649 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2650}
2651
2652/* EBGP multihop configuration. */
2653int
2654peer_ebgp_multihop_set (struct peer *peer, int ttl)
2655{
2656 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002657 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002658
2659 if (peer_sort (peer) == BGP_PEER_IBGP)
2660 return 0;
2661
2662 peer->ttl = ttl;
2663
2664 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2665 {
pauleb821182004-05-01 08:44:08 +00002666 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2667 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002668 }
2669 else
2670 {
2671 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002672 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002673 {
2674 if (peer_sort (peer) == BGP_PEER_IBGP)
2675 continue;
paul718e3742002-12-13 20:15:29 +00002676
pauleb821182004-05-01 08:44:08 +00002677 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002678
pauleb821182004-05-01 08:44:08 +00002679 if (peer->fd >= 0)
2680 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2681 }
paul718e3742002-12-13 20:15:29 +00002682 }
2683 return 0;
2684}
2685
2686int
2687peer_ebgp_multihop_unset (struct peer *peer)
2688{
2689 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002690 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002691
2692 if (peer_sort (peer) == BGP_PEER_IBGP)
2693 return 0;
2694
2695 if (peer_group_active (peer))
2696 peer->ttl = peer->group->conf->ttl;
2697 else
2698 peer->ttl = 1;
2699
2700 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2701 {
pauleb821182004-05-01 08:44:08 +00002702 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2703 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002704 }
2705 else
2706 {
2707 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002708 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002709 {
2710 if (peer_sort (peer) == BGP_PEER_IBGP)
2711 continue;
paul718e3742002-12-13 20:15:29 +00002712
pauleb821182004-05-01 08:44:08 +00002713 peer->ttl = 1;
2714
2715 if (peer->fd >= 0)
2716 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2717 }
paul718e3742002-12-13 20:15:29 +00002718 }
2719 return 0;
2720}
2721
2722/* Neighbor description. */
2723int
2724peer_description_set (struct peer *peer, char *desc)
2725{
2726 if (peer->desc)
2727 XFREE (MTYPE_PEER_DESC, peer->desc);
2728
2729 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2730
2731 return 0;
2732}
2733
2734int
2735peer_description_unset (struct peer *peer)
2736{
2737 if (peer->desc)
2738 XFREE (MTYPE_PEER_DESC, peer->desc);
2739
2740 peer->desc = NULL;
2741
2742 return 0;
2743}
2744
2745/* Neighbor update-source. */
2746int
paulfd79ac92004-10-13 05:06:08 +00002747peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002748{
2749 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002750 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002751
2752 if (peer->update_if)
2753 {
2754 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2755 && strcmp (peer->update_if, ifname) == 0)
2756 return 0;
2757
2758 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2759 peer->update_if = NULL;
2760 }
2761
2762 if (peer->update_source)
2763 {
2764 sockunion_free (peer->update_source);
2765 peer->update_source = NULL;
2766 }
2767
2768 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2769
2770 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2771 {
2772 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002773 {
2774 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2775 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2776 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2777 }
paul718e3742002-12-13 20:15:29 +00002778 else
2779 BGP_EVENT_ADD (peer, BGP_Stop);
2780 return 0;
2781 }
2782
2783 /* peer-group member updates. */
2784 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002785 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002786 {
2787 if (peer->update_if)
2788 {
2789 if (strcmp (peer->update_if, ifname) == 0)
2790 continue;
2791
2792 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2793 peer->update_if = NULL;
2794 }
2795
2796 if (peer->update_source)
2797 {
2798 sockunion_free (peer->update_source);
2799 peer->update_source = NULL;
2800 }
2801
2802 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2803
2804 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002805 {
2806 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2807 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2808 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2809 }
paul718e3742002-12-13 20:15:29 +00002810 else
2811 BGP_EVENT_ADD (peer, BGP_Stop);
2812 }
2813 return 0;
2814}
2815
2816int
2817peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2818{
2819 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002820 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002821
2822 if (peer->update_source)
2823 {
2824 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2825 && sockunion_cmp (peer->update_source, su) == 0)
2826 return 0;
2827 sockunion_free (peer->update_source);
2828 peer->update_source = NULL;
2829 }
2830
2831 if (peer->update_if)
2832 {
2833 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2834 peer->update_if = NULL;
2835 }
2836
2837 peer->update_source = sockunion_dup (su);
2838
2839 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2840 {
2841 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002842 {
2843 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2844 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2845 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2846 }
paul718e3742002-12-13 20:15:29 +00002847 else
2848 BGP_EVENT_ADD (peer, BGP_Stop);
2849 return 0;
2850 }
2851
2852 /* peer-group member updates. */
2853 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002854 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002855 {
2856 if (peer->update_source)
2857 {
2858 if (sockunion_cmp (peer->update_source, su) == 0)
2859 continue;
2860 sockunion_free (peer->update_source);
2861 peer->update_source = NULL;
2862 }
2863
2864 if (peer->update_if)
2865 {
2866 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2867 peer->update_if = NULL;
2868 }
2869
2870 peer->update_source = sockunion_dup (su);
2871
2872 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002873 {
2874 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2875 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2876 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2877 }
paul718e3742002-12-13 20:15:29 +00002878 else
2879 BGP_EVENT_ADD (peer, BGP_Stop);
2880 }
2881 return 0;
2882}
2883
2884int
2885peer_update_source_unset (struct peer *peer)
2886{
2887 union sockunion *su;
2888 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002889 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002890
2891 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2892 && ! peer->update_source
2893 && ! peer->update_if)
2894 return 0;
2895
2896 if (peer->update_source)
2897 {
2898 sockunion_free (peer->update_source);
2899 peer->update_source = NULL;
2900 }
2901 if (peer->update_if)
2902 {
2903 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2904 peer->update_if = NULL;
2905 }
2906
2907 if (peer_group_active (peer))
2908 {
2909 group = peer->group;
2910
2911 if (group->conf->update_source)
2912 {
2913 su = sockunion_dup (group->conf->update_source);
2914 peer->update_source = su;
2915 }
2916 else if (group->conf->update_if)
2917 peer->update_if =
2918 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2919 }
2920
2921 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2922 {
2923 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002924 {
2925 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2926 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2927 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2928 }
paul718e3742002-12-13 20:15:29 +00002929 else
2930 BGP_EVENT_ADD (peer, BGP_Stop);
2931 return 0;
2932 }
2933
2934 /* peer-group member updates. */
2935 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002936 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002937 {
2938 if (! peer->update_source && ! peer->update_if)
2939 continue;
2940
2941 if (peer->update_source)
2942 {
2943 sockunion_free (peer->update_source);
2944 peer->update_source = NULL;
2945 }
2946
2947 if (peer->update_if)
2948 {
2949 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2950 peer->update_if = NULL;
2951 }
2952
2953 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002954 {
2955 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2956 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2957 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2958 }
paul718e3742002-12-13 20:15:29 +00002959 else
2960 BGP_EVENT_ADD (peer, BGP_Stop);
2961 }
2962 return 0;
2963}
2964
2965int
2966peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002967 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002968{
2969 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002970 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002971
2972 /* Adress family must be activated. */
2973 if (! peer->afc[afi][safi])
2974 return BGP_ERR_PEER_INACTIVE;
2975
2976 /* Default originate can't be used for peer group memeber. */
2977 if (peer_is_group_member (peer, afi, safi))
2978 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2979
2980 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2981 || (rmap && ! peer->default_rmap[afi][safi].name)
2982 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2983 {
2984 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2985
2986 if (rmap)
2987 {
2988 if (peer->default_rmap[afi][safi].name)
2989 free (peer->default_rmap[afi][safi].name);
2990 peer->default_rmap[afi][safi].name = strdup (rmap);
2991 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2992 }
2993 }
2994
2995 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2996 {
2997 if (peer->status == Established && peer->afc_nego[afi][safi])
2998 bgp_default_originate (peer, afi, safi, 0);
2999 return 0;
3000 }
3001
3002 /* peer-group member updates. */
3003 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003004 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003005 {
3006 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3007
3008 if (rmap)
3009 {
3010 if (peer->default_rmap[afi][safi].name)
3011 free (peer->default_rmap[afi][safi].name);
3012 peer->default_rmap[afi][safi].name = strdup (rmap);
3013 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3014 }
3015
3016 if (peer->status == Established && peer->afc_nego[afi][safi])
3017 bgp_default_originate (peer, afi, safi, 0);
3018 }
3019 return 0;
3020}
3021
3022int
3023peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3024{
3025 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003026 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003027
3028 /* Adress family must be activated. */
3029 if (! peer->afc[afi][safi])
3030 return BGP_ERR_PEER_INACTIVE;
3031
3032 /* Default originate can't be used for peer group memeber. */
3033 if (peer_is_group_member (peer, afi, safi))
3034 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3035
3036 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3037 {
3038 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3039
3040 if (peer->default_rmap[afi][safi].name)
3041 free (peer->default_rmap[afi][safi].name);
3042 peer->default_rmap[afi][safi].name = NULL;
3043 peer->default_rmap[afi][safi].map = NULL;
3044 }
3045
3046 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3047 {
3048 if (peer->status == Established && peer->afc_nego[afi][safi])
3049 bgp_default_originate (peer, afi, safi, 1);
3050 return 0;
3051 }
3052
3053 /* peer-group member updates. */
3054 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003055 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003056 {
3057 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3058
3059 if (peer->default_rmap[afi][safi].name)
3060 free (peer->default_rmap[afi][safi].name);
3061 peer->default_rmap[afi][safi].name = NULL;
3062 peer->default_rmap[afi][safi].map = NULL;
3063
3064 if (peer->status == Established && peer->afc_nego[afi][safi])
3065 bgp_default_originate (peer, afi, safi, 1);
3066 }
3067 return 0;
3068}
3069
3070int
3071peer_port_set (struct peer *peer, u_int16_t port)
3072{
3073 peer->port = port;
3074 return 0;
3075}
3076
3077int
3078peer_port_unset (struct peer *peer)
3079{
3080 peer->port = BGP_PORT_DEFAULT;
3081 return 0;
3082}
3083
3084/* neighbor weight. */
3085int
3086peer_weight_set (struct peer *peer, u_int16_t weight)
3087{
3088 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003089 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003090
3091 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3092 peer->weight = weight;
3093
3094 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3095 return 0;
3096
3097 /* peer-group member updates. */
3098 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003099 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003100 {
3101 peer->weight = group->conf->weight;
3102 }
3103 return 0;
3104}
3105
3106int
3107peer_weight_unset (struct peer *peer)
3108{
3109 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003110 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003111
3112 /* Set default weight. */
3113 if (peer_group_active (peer))
3114 peer->weight = peer->group->conf->weight;
3115 else
3116 peer->weight = 0;
3117
3118 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3119
3120 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3121 return 0;
3122
3123 /* peer-group member updates. */
3124 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003125 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003126 {
3127 peer->weight = 0;
3128 }
3129 return 0;
3130}
3131
3132int
3133peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3134{
3135 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003136 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003137
3138 /* Not for peer group memeber. */
3139 if (peer_group_active (peer))
3140 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3141
3142 /* keepalive value check. */
3143 if (keepalive > 65535)
3144 return BGP_ERR_INVALID_VALUE;
3145
3146 /* Holdtime value check. */
3147 if (holdtime > 65535)
3148 return BGP_ERR_INVALID_VALUE;
3149
3150 /* Holdtime value must be either 0 or greater than 3. */
3151 if (holdtime < 3 && holdtime != 0)
3152 return BGP_ERR_INVALID_VALUE;
3153
3154 /* Set value to the configuration. */
3155 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3156 peer->holdtime = holdtime;
3157 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3158
3159 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3160 return 0;
3161
3162 /* peer-group member updates. */
3163 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003164 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003165 {
3166 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3167 peer->holdtime = group->conf->holdtime;
3168 peer->keepalive = group->conf->keepalive;
3169 }
3170 return 0;
3171}
3172
3173int
3174peer_timers_unset (struct peer *peer)
3175{
3176 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003177 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003178
3179 if (peer_group_active (peer))
3180 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3181
3182 /* Clear configuration. */
3183 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3184 peer->keepalive = 0;
3185 peer->holdtime = 0;
3186
3187 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3188 return 0;
3189
3190 /* peer-group member updates. */
3191 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003192 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003193 {
3194 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3195 peer->holdtime = 0;
3196 peer->keepalive = 0;
3197 }
3198
3199 return 0;
3200}
3201
3202int
3203peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3204{
3205 if (peer_group_active (peer))
3206 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3207
3208 if (connect > 65535)
3209 return BGP_ERR_INVALID_VALUE;
3210
3211 /* Set value to the configuration. */
3212 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3213 peer->connect = connect;
3214
3215 /* Set value to timer setting. */
3216 peer->v_connect = connect;
3217
3218 return 0;
3219}
3220
3221int
3222peer_timers_connect_unset (struct peer *peer)
3223{
3224 if (peer_group_active (peer))
3225 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3226
3227 /* Clear configuration. */
3228 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3229 peer->connect = 0;
3230
3231 /* Set timer setting to default value. */
3232 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3233
3234 return 0;
3235}
3236
3237int
3238peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3239{
3240 if (peer_group_active (peer))
3241 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3242
3243 if (routeadv > 600)
3244 return BGP_ERR_INVALID_VALUE;
3245
3246 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3247 peer->routeadv = routeadv;
3248 peer->v_routeadv = routeadv;
3249
3250 return 0;
3251}
3252
3253int
3254peer_advertise_interval_unset (struct peer *peer)
3255{
3256 if (peer_group_active (peer))
3257 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3258
3259 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3260 peer->routeadv = 0;
3261
3262 if (peer_sort (peer) == BGP_PEER_IBGP)
3263 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3264 else
3265 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3266
3267 return 0;
3268}
3269
paul718e3742002-12-13 20:15:29 +00003270/* neighbor interface */
3271int
paulfd79ac92004-10-13 05:06:08 +00003272peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003273{
3274 if (peer->ifname)
3275 free (peer->ifname);
3276 peer->ifname = strdup (str);
3277
3278 return 0;
3279}
3280
3281int
3282peer_interface_unset (struct peer *peer)
3283{
3284 if (peer->ifname)
3285 free (peer->ifname);
3286 peer->ifname = NULL;
3287
3288 return 0;
3289}
3290
3291/* Allow-as in. */
3292int
3293peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3294{
3295 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003296 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003297
3298 if (allow_num < 1 || allow_num > 10)
3299 return BGP_ERR_INVALID_VALUE;
3300
3301 if (peer->allowas_in[afi][safi] != allow_num)
3302 {
3303 peer->allowas_in[afi][safi] = allow_num;
3304 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3305 peer_change_action (peer, afi, safi, peer_change_reset_in);
3306 }
3307
3308 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3309 return 0;
3310
3311 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003312 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003313 {
3314 if (peer->allowas_in[afi][safi] != allow_num)
3315 {
3316 peer->allowas_in[afi][safi] = allow_num;
3317 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3318 peer_change_action (peer, afi, safi, peer_change_reset_in);
3319 }
3320
3321 }
3322 return 0;
3323}
3324
3325int
3326peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3327{
3328 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003329 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003330
3331 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3332 {
3333 peer->allowas_in[afi][safi] = 0;
3334 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3335 }
3336
3337 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3338 return 0;
3339
3340 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003341 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003342 {
3343 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3344 {
3345 peer->allowas_in[afi][safi] = 0;
3346 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3347 }
3348 }
3349 return 0;
3350}
3351
3352int
3353peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3354{
3355 struct bgp *bgp = peer->bgp;
3356 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003357 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003358
3359 if (peer_sort (peer) != BGP_PEER_EBGP
3360 && peer_sort (peer) != BGP_PEER_INTERNAL)
3361 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3362
3363 if (bgp->as == as)
3364 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3365
3366 if (peer_group_active (peer))
3367 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3368
3369 if (peer->change_local_as == as &&
3370 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3371 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3372 return 0;
3373
3374 peer->change_local_as = as;
3375 if (no_prepend)
3376 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3377 else
3378 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3379
3380 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3381 {
3382 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003383 {
3384 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3385 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3386 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3387 }
paul718e3742002-12-13 20:15:29 +00003388 else
3389 BGP_EVENT_ADD (peer, BGP_Stop);
3390
3391 return 0;
3392 }
3393
3394 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003395 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003396 {
3397 peer->change_local_as = as;
3398 if (no_prepend)
3399 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3400 else
3401 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3402
3403 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003404 {
3405 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3406 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3407 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3408 }
paul718e3742002-12-13 20:15:29 +00003409 else
3410 BGP_EVENT_ADD (peer, BGP_Stop);
3411 }
3412
3413 return 0;
3414}
3415
3416int
3417peer_local_as_unset (struct peer *peer)
3418{
3419 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003420 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003421
3422 if (peer_group_active (peer))
3423 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3424
3425 if (! peer->change_local_as)
3426 return 0;
3427
3428 peer->change_local_as = 0;
3429 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3430
3431 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3432 {
3433 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003434 {
3435 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3436 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3437 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3438 }
paul718e3742002-12-13 20:15:29 +00003439 else
3440 BGP_EVENT_ADD (peer, BGP_Stop);
3441
3442 return 0;
3443 }
3444
3445 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003446 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003447 {
3448 peer->change_local_as = 0;
3449 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3450
3451 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003452 {
3453 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3454 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3455 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3456 }
paul718e3742002-12-13 20:15:29 +00003457 else
3458 BGP_EVENT_ADD (peer, BGP_Stop);
3459 }
3460 return 0;
3461}
3462
Paul Jakma0df7c912008-07-21 21:02:49 +00003463/* Set password for authenticating with the peer. */
3464int
3465peer_password_set (struct peer *peer, const char *password)
3466{
3467 struct listnode *nn, *nnode;
3468 int len = password ? strlen(password) : 0;
3469 int ret = BGP_SUCCESS;
3470
3471 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3472 return BGP_ERR_INVALID_VALUE;
3473
3474 if (peer->password && strcmp (peer->password, password) == 0
3475 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3476 return 0;
3477
3478 if (peer->password)
3479 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3480
3481 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3482
3483 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3484 {
3485 if (peer->status == Established)
3486 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3487 else
3488 BGP_EVENT_ADD (peer, BGP_Stop);
3489
3490 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3491 }
3492
3493 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3494 {
3495 if (peer->password && strcmp (peer->password, password) == 0)
3496 continue;
3497
3498 if (peer->password)
3499 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3500
3501 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3502
3503 if (peer->status == Established)
3504 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3505 else
3506 BGP_EVENT_ADD (peer, BGP_Stop);
3507
3508 if (bgp_md5_set (peer) < 0)
3509 ret = BGP_ERR_TCPSIG_FAILED;
3510 }
3511
3512 return ret;
3513}
3514
3515int
3516peer_password_unset (struct peer *peer)
3517{
3518 struct listnode *nn, *nnode;
3519
3520 if (!peer->password
3521 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3522 return 0;
3523
3524 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3525 {
3526 if (peer_group_active (peer)
3527 && peer->group->conf->password
3528 && strcmp (peer->group->conf->password, peer->password) == 0)
3529 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3530
3531 if (peer->status == Established)
3532 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3533 else
3534 BGP_EVENT_ADD (peer, BGP_Stop);
3535
3536 if (peer->password)
3537 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3538
3539 peer->password = NULL;
3540
3541 bgp_md5_set (peer);
3542
3543 return 0;
3544 }
3545
3546 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3547 peer->password = NULL;
3548
3549 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3550 {
3551 if (!peer->password)
3552 continue;
3553
3554 if (peer->status == Established)
3555 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3556 else
3557 BGP_EVENT_ADD (peer, BGP_Stop);
3558
3559 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3560 peer->password = NULL;
3561
3562 bgp_md5_set (peer);
3563 }
3564
3565 return 0;
3566}
3567
paul718e3742002-12-13 20:15:29 +00003568/* Set distribute list to the peer. */
3569int
3570peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003571 const char *name)
paul718e3742002-12-13 20:15:29 +00003572{
3573 struct bgp_filter *filter;
3574 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003575 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003576
3577 if (! peer->afc[afi][safi])
3578 return BGP_ERR_PEER_INACTIVE;
3579
3580 if (direct != FILTER_IN && direct != FILTER_OUT)
3581 return BGP_ERR_INVALID_VALUE;
3582
3583 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3584 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3585
3586 filter = &peer->filter[afi][safi];
3587
3588 if (filter->plist[direct].name)
3589 return BGP_ERR_PEER_FILTER_CONFLICT;
3590
3591 if (filter->dlist[direct].name)
3592 free (filter->dlist[direct].name);
3593 filter->dlist[direct].name = strdup (name);
3594 filter->dlist[direct].alist = access_list_lookup (afi, name);
3595
3596 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3597 return 0;
3598
3599 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003600 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003601 {
3602 filter = &peer->filter[afi][safi];
3603
3604 if (! peer->af_group[afi][safi])
3605 continue;
3606
3607 if (filter->dlist[direct].name)
3608 free (filter->dlist[direct].name);
3609 filter->dlist[direct].name = strdup (name);
3610 filter->dlist[direct].alist = access_list_lookup (afi, name);
3611 }
3612
3613 return 0;
3614}
3615
3616int
3617peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3618{
3619 struct bgp_filter *filter;
3620 struct bgp_filter *gfilter;
3621 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003622 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003623
3624 if (! peer->afc[afi][safi])
3625 return BGP_ERR_PEER_INACTIVE;
3626
3627 if (direct != FILTER_IN && direct != FILTER_OUT)
3628 return BGP_ERR_INVALID_VALUE;
3629
3630 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3631 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3632
3633 filter = &peer->filter[afi][safi];
3634
3635 /* apply peer-group filter */
3636 if (peer->af_group[afi][safi])
3637 {
3638 gfilter = &peer->group->conf->filter[afi][safi];
3639
3640 if (gfilter->dlist[direct].name)
3641 {
3642 if (filter->dlist[direct].name)
3643 free (filter->dlist[direct].name);
3644 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3645 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3646 return 0;
3647 }
3648 }
3649
3650 if (filter->dlist[direct].name)
3651 free (filter->dlist[direct].name);
3652 filter->dlist[direct].name = NULL;
3653 filter->dlist[direct].alist = NULL;
3654
3655 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3656 return 0;
3657
3658 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003659 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003660 {
3661 filter = &peer->filter[afi][safi];
3662
3663 if (! peer->af_group[afi][safi])
3664 continue;
3665
3666 if (filter->dlist[direct].name)
3667 free (filter->dlist[direct].name);
3668 filter->dlist[direct].name = NULL;
3669 filter->dlist[direct].alist = NULL;
3670 }
3671
3672 return 0;
3673}
3674
3675/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003676static void
paul718e3742002-12-13 20:15:29 +00003677peer_distribute_update (struct access_list *access)
3678{
3679 afi_t afi;
3680 safi_t safi;
3681 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003682 struct listnode *mnode, *mnnode;
3683 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003684 struct bgp *bgp;
3685 struct peer *peer;
3686 struct peer_group *group;
3687 struct bgp_filter *filter;
3688
paul1eb8ef22005-04-07 07:30:20 +00003689 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003690 {
paul1eb8ef22005-04-07 07:30:20 +00003691 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003692 {
3693 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3694 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3695 {
3696 filter = &peer->filter[afi][safi];
3697
3698 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3699 {
3700 if (filter->dlist[direct].name)
3701 filter->dlist[direct].alist =
3702 access_list_lookup (afi, filter->dlist[direct].name);
3703 else
3704 filter->dlist[direct].alist = NULL;
3705 }
3706 }
3707 }
paul1eb8ef22005-04-07 07:30:20 +00003708 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003709 {
3710 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3711 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3712 {
3713 filter = &group->conf->filter[afi][safi];
3714
3715 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3716 {
3717 if (filter->dlist[direct].name)
3718 filter->dlist[direct].alist =
3719 access_list_lookup (afi, filter->dlist[direct].name);
3720 else
3721 filter->dlist[direct].alist = NULL;
3722 }
3723 }
3724 }
3725 }
3726}
3727
3728/* Set prefix list to the peer. */
3729int
3730peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003731 const char *name)
paul718e3742002-12-13 20:15:29 +00003732{
3733 struct bgp_filter *filter;
3734 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003735 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003736
3737 if (! peer->afc[afi][safi])
3738 return BGP_ERR_PEER_INACTIVE;
3739
3740 if (direct != FILTER_IN && direct != FILTER_OUT)
3741 return BGP_ERR_INVALID_VALUE;
3742
3743 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3744 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3745
3746 filter = &peer->filter[afi][safi];
3747
3748 if (filter->dlist[direct].name)
3749 return BGP_ERR_PEER_FILTER_CONFLICT;
3750
3751 if (filter->plist[direct].name)
3752 free (filter->plist[direct].name);
3753 filter->plist[direct].name = strdup (name);
3754 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3755
3756 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3757 return 0;
3758
3759 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003760 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003761 {
3762 filter = &peer->filter[afi][safi];
3763
3764 if (! peer->af_group[afi][safi])
3765 continue;
3766
3767 if (filter->plist[direct].name)
3768 free (filter->plist[direct].name);
3769 filter->plist[direct].name = strdup (name);
3770 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3771 }
3772 return 0;
3773}
3774
3775int
3776peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3777{
3778 struct bgp_filter *filter;
3779 struct bgp_filter *gfilter;
3780 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003781 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003782
3783 if (! peer->afc[afi][safi])
3784 return BGP_ERR_PEER_INACTIVE;
3785
3786 if (direct != FILTER_IN && direct != FILTER_OUT)
3787 return BGP_ERR_INVALID_VALUE;
3788
3789 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3790 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3791
3792 filter = &peer->filter[afi][safi];
3793
3794 /* apply peer-group filter */
3795 if (peer->af_group[afi][safi])
3796 {
3797 gfilter = &peer->group->conf->filter[afi][safi];
3798
3799 if (gfilter->plist[direct].name)
3800 {
3801 if (filter->plist[direct].name)
3802 free (filter->plist[direct].name);
3803 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3804 filter->plist[direct].plist = gfilter->plist[direct].plist;
3805 return 0;
3806 }
3807 }
3808
3809 if (filter->plist[direct].name)
3810 free (filter->plist[direct].name);
3811 filter->plist[direct].name = NULL;
3812 filter->plist[direct].plist = NULL;
3813
3814 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3815 return 0;
3816
3817 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003818 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003819 {
3820 filter = &peer->filter[afi][safi];
3821
3822 if (! peer->af_group[afi][safi])
3823 continue;
3824
3825 if (filter->plist[direct].name)
3826 free (filter->plist[direct].name);
3827 filter->plist[direct].name = NULL;
3828 filter->plist[direct].plist = NULL;
3829 }
3830
3831 return 0;
3832}
3833
3834/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003835static void
paul718e3742002-12-13 20:15:29 +00003836peer_prefix_list_update (struct prefix_list *plist)
3837{
paul1eb8ef22005-04-07 07:30:20 +00003838 struct listnode *mnode, *mnnode;
3839 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003840 struct bgp *bgp;
3841 struct peer *peer;
3842 struct peer_group *group;
3843 struct bgp_filter *filter;
3844 afi_t afi;
3845 safi_t safi;
3846 int direct;
3847
paul1eb8ef22005-04-07 07:30:20 +00003848 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003849 {
paul1eb8ef22005-04-07 07:30:20 +00003850 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003851 {
3852 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3853 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3854 {
3855 filter = &peer->filter[afi][safi];
3856
3857 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3858 {
3859 if (filter->plist[direct].name)
3860 filter->plist[direct].plist =
3861 prefix_list_lookup (afi, filter->plist[direct].name);
3862 else
3863 filter->plist[direct].plist = NULL;
3864 }
3865 }
3866 }
paul1eb8ef22005-04-07 07:30:20 +00003867 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003868 {
3869 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3870 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3871 {
3872 filter = &group->conf->filter[afi][safi];
3873
3874 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3875 {
3876 if (filter->plist[direct].name)
3877 filter->plist[direct].plist =
3878 prefix_list_lookup (afi, filter->plist[direct].name);
3879 else
3880 filter->plist[direct].plist = NULL;
3881 }
3882 }
3883 }
3884 }
3885}
3886
3887int
3888peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003889 const char *name)
paul718e3742002-12-13 20:15:29 +00003890{
3891 struct bgp_filter *filter;
3892 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003893 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003894
3895 if (! peer->afc[afi][safi])
3896 return BGP_ERR_PEER_INACTIVE;
3897
3898 if (direct != FILTER_IN && direct != FILTER_OUT)
3899 return BGP_ERR_INVALID_VALUE;
3900
3901 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3902 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3903
3904 filter = &peer->filter[afi][safi];
3905
3906 if (filter->aslist[direct].name)
3907 free (filter->aslist[direct].name);
3908 filter->aslist[direct].name = strdup (name);
3909 filter->aslist[direct].aslist = as_list_lookup (name);
3910
3911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3912 return 0;
3913
3914 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003915 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003916 {
3917 filter = &peer->filter[afi][safi];
3918
3919 if (! peer->af_group[afi][safi])
3920 continue;
3921
3922 if (filter->aslist[direct].name)
3923 free (filter->aslist[direct].name);
3924 filter->aslist[direct].name = strdup (name);
3925 filter->aslist[direct].aslist = as_list_lookup (name);
3926 }
3927 return 0;
3928}
3929
3930int
3931peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3932{
3933 struct bgp_filter *filter;
3934 struct bgp_filter *gfilter;
3935 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003936 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003937
3938 if (! peer->afc[afi][safi])
3939 return BGP_ERR_PEER_INACTIVE;
3940
hassob5f29602005-05-25 21:00:28 +00003941 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003942 return BGP_ERR_INVALID_VALUE;
3943
hassob5f29602005-05-25 21:00:28 +00003944 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003945 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3946
3947 filter = &peer->filter[afi][safi];
3948
3949 /* apply peer-group filter */
3950 if (peer->af_group[afi][safi])
3951 {
3952 gfilter = &peer->group->conf->filter[afi][safi];
3953
3954 if (gfilter->aslist[direct].name)
3955 {
3956 if (filter->aslist[direct].name)
3957 free (filter->aslist[direct].name);
3958 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3959 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3960 return 0;
3961 }
3962 }
3963
3964 if (filter->aslist[direct].name)
3965 free (filter->aslist[direct].name);
3966 filter->aslist[direct].name = NULL;
3967 filter->aslist[direct].aslist = NULL;
3968
3969 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3970 return 0;
3971
3972 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003973 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003974 {
3975 filter = &peer->filter[afi][safi];
3976
3977 if (! peer->af_group[afi][safi])
3978 continue;
3979
3980 if (filter->aslist[direct].name)
3981 free (filter->aslist[direct].name);
3982 filter->aslist[direct].name = NULL;
3983 filter->aslist[direct].aslist = NULL;
3984 }
3985
3986 return 0;
3987}
3988
paul94f2b392005-06-28 12:44:16 +00003989static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003990peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003991{
3992 afi_t afi;
3993 safi_t safi;
3994 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003995 struct listnode *mnode, *mnnode;
3996 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003997 struct bgp *bgp;
3998 struct peer *peer;
3999 struct peer_group *group;
4000 struct bgp_filter *filter;
4001
paul1eb8ef22005-04-07 07:30:20 +00004002 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004003 {
paul1eb8ef22005-04-07 07:30:20 +00004004 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004005 {
4006 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4007 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4008 {
4009 filter = &peer->filter[afi][safi];
4010
4011 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4012 {
4013 if (filter->aslist[direct].name)
4014 filter->aslist[direct].aslist =
4015 as_list_lookup (filter->aslist[direct].name);
4016 else
4017 filter->aslist[direct].aslist = NULL;
4018 }
4019 }
4020 }
paul1eb8ef22005-04-07 07:30:20 +00004021 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004022 {
4023 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4024 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4025 {
4026 filter = &group->conf->filter[afi][safi];
4027
4028 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4029 {
4030 if (filter->aslist[direct].name)
4031 filter->aslist[direct].aslist =
4032 as_list_lookup (filter->aslist[direct].name);
4033 else
4034 filter->aslist[direct].aslist = NULL;
4035 }
4036 }
4037 }
4038 }
4039}
4040
4041/* Set route-map to the peer. */
4042int
4043peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004044 const char *name)
paul718e3742002-12-13 20:15:29 +00004045{
4046 struct bgp_filter *filter;
4047 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004048 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004049
4050 if (! peer->afc[afi][safi])
4051 return BGP_ERR_PEER_INACTIVE;
4052
paulfee0f4c2004-09-13 05:12:46 +00004053 if (direct != RMAP_IN && direct != RMAP_OUT &&
4054 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004055 return BGP_ERR_INVALID_VALUE;
4056
paulfee0f4c2004-09-13 05:12:46 +00004057 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4058 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004059 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4060
4061 filter = &peer->filter[afi][safi];
4062
4063 if (filter->map[direct].name)
4064 free (filter->map[direct].name);
4065
4066 filter->map[direct].name = strdup (name);
4067 filter->map[direct].map = route_map_lookup_by_name (name);
4068
4069 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4070 return 0;
4071
4072 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004073 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004074 {
4075 filter = &peer->filter[afi][safi];
4076
4077 if (! peer->af_group[afi][safi])
4078 continue;
4079
4080 if (filter->map[direct].name)
4081 free (filter->map[direct].name);
4082 filter->map[direct].name = strdup (name);
4083 filter->map[direct].map = route_map_lookup_by_name (name);
4084 }
4085 return 0;
4086}
4087
4088/* Unset route-map from the peer. */
4089int
4090peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4091{
4092 struct bgp_filter *filter;
4093 struct bgp_filter *gfilter;
4094 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004095 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004096
4097 if (! peer->afc[afi][safi])
4098 return BGP_ERR_PEER_INACTIVE;
4099
hassob5f29602005-05-25 21:00:28 +00004100 if (direct != RMAP_IN && direct != RMAP_OUT &&
4101 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004102 return BGP_ERR_INVALID_VALUE;
4103
hassob5f29602005-05-25 21:00:28 +00004104 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4105 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004106 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4107
4108 filter = &peer->filter[afi][safi];
4109
4110 /* apply peer-group filter */
4111 if (peer->af_group[afi][safi])
4112 {
4113 gfilter = &peer->group->conf->filter[afi][safi];
4114
4115 if (gfilter->map[direct].name)
4116 {
4117 if (filter->map[direct].name)
4118 free (filter->map[direct].name);
4119 filter->map[direct].name = strdup (gfilter->map[direct].name);
4120 filter->map[direct].map = gfilter->map[direct].map;
4121 return 0;
4122 }
4123 }
4124
4125 if (filter->map[direct].name)
4126 free (filter->map[direct].name);
4127 filter->map[direct].name = NULL;
4128 filter->map[direct].map = NULL;
4129
4130 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4131 return 0;
4132
4133 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004134 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004135 {
4136 filter = &peer->filter[afi][safi];
4137
4138 if (! peer->af_group[afi][safi])
4139 continue;
4140
4141 if (filter->map[direct].name)
4142 free (filter->map[direct].name);
4143 filter->map[direct].name = NULL;
4144 filter->map[direct].map = NULL;
4145 }
4146 return 0;
4147}
4148
4149/* Set unsuppress-map to the peer. */
4150int
paulfd79ac92004-10-13 05:06:08 +00004151peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4152 const char *name)
paul718e3742002-12-13 20:15:29 +00004153{
4154 struct bgp_filter *filter;
4155 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004157
4158 if (! peer->afc[afi][safi])
4159 return BGP_ERR_PEER_INACTIVE;
4160
4161 if (peer_is_group_member (peer, afi, safi))
4162 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4163
4164 filter = &peer->filter[afi][safi];
4165
4166 if (filter->usmap.name)
4167 free (filter->usmap.name);
4168
4169 filter->usmap.name = strdup (name);
4170 filter->usmap.map = route_map_lookup_by_name (name);
4171
4172 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4173 return 0;
4174
4175 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004176 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004177 {
4178 filter = &peer->filter[afi][safi];
4179
4180 if (! peer->af_group[afi][safi])
4181 continue;
4182
4183 if (filter->usmap.name)
4184 free (filter->usmap.name);
4185 filter->usmap.name = strdup (name);
4186 filter->usmap.map = route_map_lookup_by_name (name);
4187 }
4188 return 0;
4189}
4190
4191/* Unset route-map from the peer. */
4192int
4193peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4194{
4195 struct bgp_filter *filter;
4196 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004197 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004198
4199 if (! peer->afc[afi][safi])
4200 return BGP_ERR_PEER_INACTIVE;
4201
4202 if (peer_is_group_member (peer, afi, safi))
4203 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4204
4205 filter = &peer->filter[afi][safi];
4206
4207 if (filter->usmap.name)
4208 free (filter->usmap.name);
4209 filter->usmap.name = NULL;
4210 filter->usmap.map = NULL;
4211
4212 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4213 return 0;
4214
4215 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004216 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004217 {
4218 filter = &peer->filter[afi][safi];
4219
4220 if (! peer->af_group[afi][safi])
4221 continue;
4222
4223 if (filter->usmap.name)
4224 free (filter->usmap.name);
4225 filter->usmap.name = NULL;
4226 filter->usmap.map = NULL;
4227 }
4228 return 0;
4229}
4230
4231int
4232peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004233 u_int32_t max, u_char threshold,
4234 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004235{
4236 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004237 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004238
4239 if (! peer->afc[afi][safi])
4240 return BGP_ERR_PEER_INACTIVE;
4241
4242 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4243 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004244 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004245 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004246 if (warning)
4247 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4248 else
4249 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4250
4251 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4252 return 0;
4253
4254 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004255 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004256 {
4257 if (! peer->af_group[afi][safi])
4258 continue;
4259
4260 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4261 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004262 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004263 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004264 if (warning)
4265 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4266 else
4267 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4268 }
4269 return 0;
4270}
4271
4272int
4273peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4274{
4275 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004276 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004277
4278 if (! peer->afc[afi][safi])
4279 return BGP_ERR_PEER_INACTIVE;
4280
4281 /* apply peer-group config */
4282 if (peer->af_group[afi][safi])
4283 {
4284 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4285 PEER_FLAG_MAX_PREFIX))
4286 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4287 else
4288 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4289
4290 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4291 PEER_FLAG_MAX_PREFIX_WARNING))
4292 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4293 else
4294 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4295
4296 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004297 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004298 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004299 return 0;
4300 }
4301
4302 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4303 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4304 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004305 peer->pmax_threshold[afi][safi] = 0;
4306 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004307
4308 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4309 return 0;
4310
4311 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004312 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004313 {
4314 if (! peer->af_group[afi][safi])
4315 continue;
4316
4317 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4318 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4319 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004320 peer->pmax_threshold[afi][safi] = 0;
4321 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004322 }
4323 return 0;
4324}
4325
4326int
4327peer_clear (struct peer *peer)
4328{
4329 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4330 {
hasso0a486e52005-02-01 20:57:17 +00004331 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4332 {
4333 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4334 if (peer->t_pmax_restart)
4335 {
4336 BGP_TIMER_OFF (peer->t_pmax_restart);
4337 if (BGP_DEBUG (events, EVENTS))
4338 zlog_debug ("%s Maximum-prefix restart timer canceled",
4339 peer->host);
4340 }
4341 BGP_EVENT_ADD (peer, BGP_Start);
4342 return 0;
4343 }
4344
paul718e3742002-12-13 20:15:29 +00004345 peer->v_start = BGP_INIT_START_TIMER;
4346 if (peer->status == Established)
4347 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4348 BGP_NOTIFY_CEASE_ADMIN_RESET);
4349 else
4350 BGP_EVENT_ADD (peer, BGP_Stop);
4351 }
4352 return 0;
4353}
4354
4355int
4356peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4357 enum bgp_clear_type stype)
4358{
4359 if (peer->status != Established)
4360 return 0;
4361
4362 if (! peer->afc[afi][safi])
4363 return BGP_ERR_AF_UNCONFIGURED;
4364
paulfee0f4c2004-09-13 05:12:46 +00004365 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4366 {
4367 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4368 return 0;
4369 bgp_check_local_routes_rsclient (peer, afi, safi);
4370 bgp_soft_reconfig_rsclient (peer, afi, safi);
4371 }
4372
paul718e3742002-12-13 20:15:29 +00004373 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4374 bgp_announce_route (peer, afi, safi);
4375
4376 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4377 {
4378 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4379 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4380 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4381 {
4382 struct bgp_filter *filter = &peer->filter[afi][safi];
4383 u_char prefix_type;
4384
4385 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4386 prefix_type = ORF_TYPE_PREFIX;
4387 else
4388 prefix_type = ORF_TYPE_PREFIX_OLD;
4389
4390 if (filter->plist[FILTER_IN].plist)
4391 {
4392 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4393 bgp_route_refresh_send (peer, afi, safi,
4394 prefix_type, REFRESH_DEFER, 1);
4395 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4396 REFRESH_IMMEDIATE, 0);
4397 }
4398 else
4399 {
4400 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4401 bgp_route_refresh_send (peer, afi, safi,
4402 prefix_type, REFRESH_IMMEDIATE, 1);
4403 else
4404 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4405 }
4406 return 0;
4407 }
4408 }
4409
4410 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4411 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4412 {
4413 /* If neighbor has soft reconfiguration inbound flag.
4414 Use Adj-RIB-In database. */
4415 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4416 bgp_soft_reconfig_in (peer, afi, safi);
4417 else
4418 {
4419 /* If neighbor has route refresh capability, send route refresh
4420 message to the peer. */
4421 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4422 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4423 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4424 else
4425 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4426 }
4427 }
4428 return 0;
4429}
4430
paulfd79ac92004-10-13 05:06:08 +00004431/* Display peer uptime.*/
4432/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004433char *
4434peer_uptime (time_t uptime2, char *buf, size_t len)
4435{
4436 time_t uptime1;
4437 struct tm *tm;
4438
4439 /* Check buffer length. */
4440 if (len < BGP_UPTIME_LEN)
4441 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004442 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004443 /* XXX: should return status instead of buf... */
4444 snprintf (buf, len, "<error> ");
4445 return buf;
paul718e3742002-12-13 20:15:29 +00004446 }
4447
4448 /* If there is no connection has been done before print `never'. */
4449 if (uptime2 == 0)
4450 {
4451 snprintf (buf, len, "never ");
4452 return buf;
4453 }
4454
4455 /* Get current time. */
4456 uptime1 = time (NULL);
4457 uptime1 -= uptime2;
4458 tm = gmtime (&uptime1);
4459
4460 /* Making formatted timer strings. */
4461#define ONE_DAY_SECOND 60*60*24
4462#define ONE_WEEK_SECOND 60*60*24*7
4463
4464 if (uptime1 < ONE_DAY_SECOND)
4465 snprintf (buf, len, "%02d:%02d:%02d",
4466 tm->tm_hour, tm->tm_min, tm->tm_sec);
4467 else if (uptime1 < ONE_WEEK_SECOND)
4468 snprintf (buf, len, "%dd%02dh%02dm",
4469 tm->tm_yday, tm->tm_hour, tm->tm_min);
4470 else
4471 snprintf (buf, len, "%02dw%dd%02dh",
4472 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4473 return buf;
4474}
4475
paul94f2b392005-06-28 12:44:16 +00004476static void
paul718e3742002-12-13 20:15:29 +00004477bgp_config_write_filter (struct vty *vty, struct peer *peer,
4478 afi_t afi, safi_t safi)
4479{
4480 struct bgp_filter *filter;
4481 struct bgp_filter *gfilter = NULL;
4482 char *addr;
4483 int in = FILTER_IN;
4484 int out = FILTER_OUT;
4485
4486 addr = peer->host;
4487 filter = &peer->filter[afi][safi];
4488 if (peer->af_group[afi][safi])
4489 gfilter = &peer->group->conf->filter[afi][safi];
4490
4491 /* distribute-list. */
4492 if (filter->dlist[in].name)
4493 if (! gfilter || ! gfilter->dlist[in].name
4494 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4495 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4496 filter->dlist[in].name, VTY_NEWLINE);
4497 if (filter->dlist[out].name && ! gfilter)
4498 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4499 filter->dlist[out].name, VTY_NEWLINE);
4500
4501 /* prefix-list. */
4502 if (filter->plist[in].name)
4503 if (! gfilter || ! gfilter->plist[in].name
4504 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4505 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4506 filter->plist[in].name, VTY_NEWLINE);
4507 if (filter->plist[out].name && ! gfilter)
4508 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4509 filter->plist[out].name, VTY_NEWLINE);
4510
4511 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004512 if (filter->map[RMAP_IN].name)
4513 if (! gfilter || ! gfilter->map[RMAP_IN].name
4514 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004515 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004516 filter->map[RMAP_IN].name, VTY_NEWLINE);
4517 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004518 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004519 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4520 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4521 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4522 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4523 if (filter->map[RMAP_EXPORT].name)
4524 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4525 || strcmp (filter->map[RMAP_EXPORT].name,
4526 gfilter->map[RMAP_EXPORT].name) != 0)
4527 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4528 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004529
4530 /* unsuppress-map */
4531 if (filter->usmap.name && ! gfilter)
4532 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4533 filter->usmap.name, VTY_NEWLINE);
4534
4535 /* filter-list. */
4536 if (filter->aslist[in].name)
4537 if (! gfilter || ! gfilter->aslist[in].name
4538 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4539 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4540 filter->aslist[in].name, VTY_NEWLINE);
4541 if (filter->aslist[out].name && ! gfilter)
4542 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4543 filter->aslist[out].name, VTY_NEWLINE);
4544}
4545
4546/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004547static void
paul718e3742002-12-13 20:15:29 +00004548bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4549 struct peer *peer, afi_t afi, safi_t safi)
4550{
4551 struct bgp_filter *filter;
4552 struct peer *g_peer = NULL;
4553 char buf[SU_ADDRSTRLEN];
4554 char *addr;
4555
4556 filter = &peer->filter[afi][safi];
4557 addr = peer->host;
4558 if (peer_group_active (peer))
4559 g_peer = peer->group->conf;
4560
4561 /************************************
4562 ****** Global to the neighbor ******
4563 ************************************/
4564 if (afi == AFI_IP && safi == SAFI_UNICAST)
4565 {
4566 /* remote-as. */
4567 if (! peer_group_active (peer))
4568 {
4569 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4570 vty_out (vty, " neighbor %s peer-group%s", addr,
4571 VTY_NEWLINE);
4572 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004573 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004574 VTY_NEWLINE);
4575 }
4576 else
4577 {
4578 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004579 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004580 VTY_NEWLINE);
4581 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4582 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4583 peer->group->name, VTY_NEWLINE);
4584 }
4585
4586 /* local-as. */
4587 if (peer->change_local_as)
4588 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004589 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004590 peer->change_local_as,
4591 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4592 " no-prepend" : "", VTY_NEWLINE);
4593
4594 /* Description. */
4595 if (peer->desc)
4596 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4597 VTY_NEWLINE);
4598
4599 /* Shutdown. */
4600 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4601 if (! peer_group_active (peer) ||
4602 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4603 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4604
Paul Jakma0df7c912008-07-21 21:02:49 +00004605 /* Password. */
4606 if (peer->password)
4607 if (!peer_group_active (peer)
4608 || ! g_peer->password
4609 || strcmp (peer->password, g_peer->password) != 0)
4610 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4611 VTY_NEWLINE);
4612
paul718e3742002-12-13 20:15:29 +00004613 /* BGP port. */
4614 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004615 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004616 VTY_NEWLINE);
4617
4618 /* Local interface name. */
4619 if (peer->ifname)
4620 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4621 VTY_NEWLINE);
4622
4623 /* Passive. */
4624 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4625 if (! peer_group_active (peer) ||
4626 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4627 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4628
4629 /* EBGP multihop. */
4630 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4631 if (! peer_group_active (peer) ||
4632 g_peer->ttl != peer->ttl)
4633 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4634 VTY_NEWLINE);
4635
hasso6ffd2072005-02-02 14:50:11 +00004636 /* disable-connected-check. */
4637 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004638 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004639 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4640 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004641
4642 /* Update-source. */
4643 if (peer->update_if)
4644 if (! peer_group_active (peer) || ! g_peer->update_if
4645 || strcmp (g_peer->update_if, peer->update_if) != 0)
4646 vty_out (vty, " neighbor %s update-source %s%s", addr,
4647 peer->update_if, VTY_NEWLINE);
4648 if (peer->update_source)
4649 if (! peer_group_active (peer) || ! g_peer->update_source
4650 || sockunion_cmp (g_peer->update_source,
4651 peer->update_source) != 0)
4652 vty_out (vty, " neighbor %s update-source %s%s", addr,
4653 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4654 VTY_NEWLINE);
4655
paul718e3742002-12-13 20:15:29 +00004656 /* advertisement-interval */
4657 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4658 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4659 addr, peer->v_routeadv, VTY_NEWLINE);
4660
4661 /* timers. */
4662 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4663 && ! peer_group_active (peer))
4664 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4665 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4666
4667 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4668 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4669 peer->connect, VTY_NEWLINE);
4670
4671 /* Default weight. */
4672 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4673 if (! peer_group_active (peer) ||
4674 g_peer->weight != peer->weight)
4675 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4676 VTY_NEWLINE);
4677
paul718e3742002-12-13 20:15:29 +00004678 /* Dynamic capability. */
4679 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4680 if (! peer_group_active (peer) ||
4681 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4682 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4683 VTY_NEWLINE);
4684
4685 /* dont capability negotiation. */
4686 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4687 if (! peer_group_active (peer) ||
4688 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4689 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4690 VTY_NEWLINE);
4691
4692 /* override capability negotiation. */
4693 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4694 if (! peer_group_active (peer) ||
4695 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4696 vty_out (vty, " neighbor %s override-capability%s", addr,
4697 VTY_NEWLINE);
4698
4699 /* strict capability negotiation. */
4700 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4701 if (! peer_group_active (peer) ||
4702 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4703 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4704 VTY_NEWLINE);
4705
4706 if (! peer_group_active (peer))
4707 {
4708 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4709 {
4710 if (peer->afc[AFI_IP][SAFI_UNICAST])
4711 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4712 }
4713 else
4714 {
4715 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4716 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4717 }
4718 }
4719 }
4720
4721
4722 /************************************
4723 ****** Per AF to the neighbor ******
4724 ************************************/
4725
4726 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4727 {
4728 if (peer->af_group[afi][safi])
4729 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4730 peer->group->name, VTY_NEWLINE);
4731 else
4732 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4733 }
4734
4735 /* ORF capability. */
4736 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4737 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4738 if (! peer->af_group[afi][safi])
4739 {
4740 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4741
4742 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4743 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4744 vty_out (vty, " both");
4745 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4746 vty_out (vty, " send");
4747 else
4748 vty_out (vty, " receive");
4749 vty_out (vty, "%s", VTY_NEWLINE);
4750 }
4751
4752 /* Route reflector client. */
4753 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4754 && ! peer->af_group[afi][safi])
4755 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4756 VTY_NEWLINE);
4757
4758 /* Nexthop self. */
4759 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4760 && ! peer->af_group[afi][safi])
4761 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4762
4763 /* Remove private AS. */
4764 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4765 && ! peer->af_group[afi][safi])
4766 vty_out (vty, " neighbor %s remove-private-AS%s",
4767 addr, VTY_NEWLINE);
4768
4769 /* send-community print. */
4770 if (! peer->af_group[afi][safi])
4771 {
4772 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4773 {
4774 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4775 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4776 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4777 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4778 vty_out (vty, " neighbor %s send-community extended%s",
4779 addr, VTY_NEWLINE);
4780 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4781 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4782 }
4783 else
4784 {
4785 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4786 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4787 vty_out (vty, " no neighbor %s send-community both%s",
4788 addr, VTY_NEWLINE);
4789 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4790 vty_out (vty, " no neighbor %s send-community extended%s",
4791 addr, VTY_NEWLINE);
4792 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4793 vty_out (vty, " no neighbor %s send-community%s",
4794 addr, VTY_NEWLINE);
4795 }
4796 }
4797
4798 /* Default information */
4799 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4800 && ! peer->af_group[afi][safi])
4801 {
4802 vty_out (vty, " neighbor %s default-originate", addr);
4803 if (peer->default_rmap[afi][safi].name)
4804 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4805 vty_out (vty, "%s", VTY_NEWLINE);
4806 }
4807
4808 /* Soft reconfiguration inbound. */
4809 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4810 if (! peer->af_group[afi][safi] ||
4811 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4812 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4813 VTY_NEWLINE);
4814
4815 /* maximum-prefix. */
4816 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4817 if (! peer->af_group[afi][safi]
4818 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004819 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004820 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4821 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004822 {
hasso0a486e52005-02-01 20:57:17 +00004823 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4824 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4825 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4826 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4827 vty_out (vty, " warning-only");
4828 if (peer->pmax_restart[afi][safi])
4829 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4830 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004831 }
paul718e3742002-12-13 20:15:29 +00004832
4833 /* Route server client. */
4834 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4835 && ! peer->af_group[afi][safi])
4836 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4837
4838 /* Allow AS in. */
4839 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4840 if (! peer_group_active (peer)
4841 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4842 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4843 {
4844 if (peer->allowas_in[afi][safi] == 3)
4845 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4846 else
4847 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4848 peer->allowas_in[afi][safi], VTY_NEWLINE);
4849 }
4850
4851 /* Filter. */
4852 bgp_config_write_filter (vty, peer, afi, safi);
4853
4854 /* atribute-unchanged. */
4855 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4856 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4857 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4858 && ! peer->af_group[afi][safi])
4859 {
4860 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4861 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4862 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4863 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4864 else
4865 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4866 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4867 " as-path" : "",
4868 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4869 " next-hop" : "",
4870 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4871 " med" : "", VTY_NEWLINE);
4872 }
4873}
4874
4875/* Display "address-family" configuration header. */
4876void
4877bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4878 int *write)
4879{
4880 if (*write)
4881 return;
4882
4883 if (afi == AFI_IP && safi == SAFI_UNICAST)
4884 return;
4885
4886 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4887
4888 if (afi == AFI_IP)
4889 {
4890 if (safi == SAFI_MULTICAST)
4891 vty_out (vty, "ipv4 multicast");
4892 else if (safi == SAFI_MPLS_VPN)
4893 vty_out (vty, "vpnv4 unicast");
4894 }
4895 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004896 {
4897 vty_out (vty, "ipv6");
4898
4899 if (safi == SAFI_MULTICAST)
4900 vty_out (vty, " multicast");
4901 }
paul718e3742002-12-13 20:15:29 +00004902
4903 vty_out (vty, "%s", VTY_NEWLINE);
4904
4905 *write = 1;
4906}
4907
4908/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004909static int
paul718e3742002-12-13 20:15:29 +00004910bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4911 safi_t safi)
4912{
4913 int write = 0;
4914 struct peer *peer;
4915 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004916 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004917
4918 bgp_config_write_network (vty, bgp, afi, safi, &write);
4919
4920 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4921
paul1eb8ef22005-04-07 07:30:20 +00004922 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004923 {
4924 if (group->conf->afc[afi][safi])
4925 {
4926 bgp_config_write_family_header (vty, afi, safi, &write);
4927 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4928 }
4929 }
paul1eb8ef22005-04-07 07:30:20 +00004930 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004931 {
4932 if (peer->afc[afi][safi])
4933 {
4934 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4935 {
4936 bgp_config_write_family_header (vty, afi, safi, &write);
4937 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4938 }
4939 }
4940 }
4941 if (write)
4942 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4943
4944 return write;
4945}
4946
4947int
4948bgp_config_write (struct vty *vty)
4949{
4950 int write = 0;
4951 struct bgp *bgp;
4952 struct peer_group *group;
4953 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004954 struct listnode *node, *nnode;
4955 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004956
4957 /* BGP Multiple instance. */
4958 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4959 {
4960 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4961 write++;
4962 }
4963
4964 /* BGP Config type. */
4965 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4966 {
4967 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4968 write++;
4969 }
4970
4971 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004972 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004973 {
4974 if (write)
4975 vty_out (vty, "!%s", VTY_NEWLINE);
4976
4977 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004978 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004979
4980 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4981 {
4982 if (bgp->name)
4983 vty_out (vty, " view %s", bgp->name);
4984 }
4985 vty_out (vty, "%s", VTY_NEWLINE);
4986
4987 /* No Synchronization */
4988 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4989 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4990
4991 /* BGP fast-external-failover. */
4992 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4993 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4994
4995 /* BGP router ID. */
4996 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4997 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4998 VTY_NEWLINE);
4999
paul848973c2003-08-13 00:32:49 +00005000 /* BGP log-neighbor-changes. */
5001 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5002 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5003
paul718e3742002-12-13 20:15:29 +00005004 /* BGP configuration. */
5005 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5006 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5007
5008 /* BGP default ipv4-unicast. */
5009 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5010 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5011
5012 /* BGP default local-preference. */
5013 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5014 vty_out (vty, " bgp default local-preference %d%s",
5015 bgp->default_local_pref, VTY_NEWLINE);
5016
5017 /* BGP client-to-client reflection. */
5018 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5019 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5020
5021 /* BGP cluster ID. */
5022 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5023 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5024 VTY_NEWLINE);
5025
hassoe0701b72004-05-20 09:19:34 +00005026 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005027 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005028 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5029 VTY_NEWLINE);
5030
5031 /* Confederation peer */
5032 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005033 {
hassoe0701b72004-05-20 09:19:34 +00005034 int i;
paul718e3742002-12-13 20:15:29 +00005035
hassoe0701b72004-05-20 09:19:34 +00005036 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005037
hassoe0701b72004-05-20 09:19:34 +00005038 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005039 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005040
hassoe0701b72004-05-20 09:19:34 +00005041 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005042 }
5043
5044 /* BGP enforce-first-as. */
5045 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5046 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5047
5048 /* BGP deterministic-med. */
5049 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5050 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005051
5052 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005053 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5054 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5055 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005056 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5057 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5058
paul718e3742002-12-13 20:15:29 +00005059 /* BGP bestpath method. */
5060 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5061 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005062 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5063 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005064 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5065 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5066 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5067 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5068 {
5069 vty_out (vty, " bgp bestpath med");
5070 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5071 vty_out (vty, " confed");
5072 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5073 vty_out (vty, " missing-as-worst");
5074 vty_out (vty, "%s", VTY_NEWLINE);
5075 }
5076
5077 /* BGP network import check. */
5078 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5079 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5080
5081 /* BGP scan interval. */
5082 bgp_config_write_scan_time (vty);
5083
5084 /* BGP flag dampening. */
5085 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5086 BGP_CONFIG_DAMPENING))
5087 bgp_config_write_damp (vty);
5088
5089 /* BGP static route configuration. */
5090 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5091
5092 /* BGP redistribute configuration. */
5093 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5094
5095 /* BGP timers configuration. */
5096 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5097 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5098 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5099 bgp->default_holdtime, VTY_NEWLINE);
5100
5101 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005102 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005103 {
5104 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5105 }
5106
5107 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005108 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005109 {
5110 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5111 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5112 }
5113
5114 /* Distance configuration. */
5115 bgp_config_write_distance (vty, bgp);
5116
5117 /* No auto-summary */
5118 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5119 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5120
5121 /* IPv4 multicast configuration. */
5122 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5123
5124 /* IPv4 VPN configuration. */
5125 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5126
5127 /* IPv6 unicast configuration. */
5128 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5129
Paul Jakma37a217a2007-04-10 19:20:29 +00005130 /* IPv6 multicast configuration. */
5131 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5132
paul718e3742002-12-13 20:15:29 +00005133 write++;
5134 }
5135 return write;
5136}
5137
5138void
paul94f2b392005-06-28 12:44:16 +00005139bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005140{
5141 memset (&bgp_master, 0, sizeof (struct bgp_master));
5142
5143 bm = &bgp_master;
5144 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005145 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005146 bm->port = BGP_PORT_DEFAULT;
5147 bm->master = thread_master_create ();
5148 bm->start_time = time (NULL);
5149}
paul200df112005-06-01 11:17:05 +00005150
paul718e3742002-12-13 20:15:29 +00005151
5152void
paul94f2b392005-06-28 12:44:16 +00005153bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005154{
paul718e3742002-12-13 20:15:29 +00005155 /* BGP VTY commands installation. */
5156 bgp_vty_init ();
5157
paul718e3742002-12-13 20:15:29 +00005158 /* Init zebra. */
5159 bgp_zebra_init ();
5160
5161 /* BGP inits. */
5162 bgp_attr_init ();
5163 bgp_debug_init ();
5164 bgp_dump_init ();
5165 bgp_route_init ();
5166 bgp_route_map_init ();
5167 bgp_scan_init ();
5168 bgp_mplsvpn_init ();
5169
5170 /* Access list initialize. */
5171 access_list_init ();
5172 access_list_add_hook (peer_distribute_update);
5173 access_list_delete_hook (peer_distribute_update);
5174
5175 /* Filter list initialize. */
5176 bgp_filter_init ();
5177 as_list_add_hook (peer_aslist_update);
5178 as_list_delete_hook (peer_aslist_update);
5179
5180 /* Prefix list initialize.*/
5181 prefix_list_init ();
5182 prefix_list_add_hook (peer_prefix_list_update);
5183 prefix_list_delete_hook (peer_prefix_list_update);
5184
5185 /* Community list initialize. */
5186 bgp_clist = community_list_init ();
5187
5188#ifdef HAVE_SNMP
5189 bgp_snmp_init ();
5190#endif /* HAVE_SNMP */
5191}
paul545acaf2004-04-20 15:13:15 +00005192
5193void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005194bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005195{
paul545acaf2004-04-20 15:13:15 +00005196 struct bgp *bgp;
5197 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005198 struct listnode *node, *nnode;
5199 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005200
paul1eb8ef22005-04-07 07:30:20 +00005201 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5202 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005203 if (peer->status == Established)
5204 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5205 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005206
paul545acaf2004-04-20 15:13:15 +00005207 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005208
paule210cf92005-06-15 19:15:35 +00005209 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005210 {
5211 work_queue_free (bm->process_main_queue);
5212 bm->process_main_queue = NULL;
5213 }
paule210cf92005-06-15 19:15:35 +00005214 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005215 {
5216 work_queue_free (bm->process_rsclient_queue);
5217 bm->process_rsclient_queue = NULL;
5218 }
paul545acaf2004-04-20 15:13:15 +00005219}