blob: ef8fbe9755aebf81f5260d9f9a106d32d5a5e6ff [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
hasso18a6dce2004-10-03 18:18:34 +000067extern struct in_addr router_id_zebra;
68
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000088 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000107 }
108 return 0;
109}
110
111int
112bgp_option_check (int flag)
113{
114 return CHECK_FLAG (bm->options, flag);
115}
116
117/* BGP flag manipulation. */
118int
119bgp_flag_set (struct bgp *bgp, int flag)
120{
121 SET_FLAG (bgp->flags, flag);
122 return 0;
123}
124
125int
126bgp_flag_unset (struct bgp *bgp, int flag)
127{
128 UNSET_FLAG (bgp->flags, flag);
129 return 0;
130}
131
132int
133bgp_flag_check (struct bgp *bgp, int flag)
134{
135 return CHECK_FLAG (bgp->flags, flag);
136}
137
138/* Internal function to set BGP structure configureation flag. */
139static void
140bgp_config_set (struct bgp *bgp, int config)
141{
142 SET_FLAG (bgp->config, config);
143}
144
145static void
146bgp_config_unset (struct bgp *bgp, int config)
147{
148 UNSET_FLAG (bgp->config, config);
149}
150
151static int
152bgp_config_check (struct bgp *bgp, int config)
153{
154 return CHECK_FLAG (bgp->config, config);
155}
156
157/* Set BGP router identifier. */
158int
159bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
160{
161 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000163
164 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
165 && IPV4_ADDR_SAME (&bgp->router_id, id))
166 return 0;
167
168 IPV4_ADDR_COPY (&bgp->router_id, id);
169 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
170
171 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000173 {
174 IPV4_ADDR_COPY (&peer->local_id, id);
175
176 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000177 {
178 peer->last_reset = PEER_DOWN_RID_CHANGE;
179 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
180 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
181 }
paul718e3742002-12-13 20:15:29 +0000182 }
183 return 0;
184}
185
paul718e3742002-12-13 20:15:29 +0000186/* BGP's cluster-id control. */
187int
188bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
189{
190 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000191 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000192
193 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
194 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
195 return 0;
196
197 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
198 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
199
200 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000202 {
203 if (peer_sort (peer) != BGP_PEER_IBGP)
204 continue;
205
206 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000207 {
208 peer->last_reset = PEER_DOWN_CLID_CHANGE;
209 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
210 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
211 }
paul718e3742002-12-13 20:15:29 +0000212 }
213 return 0;
214}
215
216int
217bgp_cluster_id_unset (struct bgp *bgp)
218{
219 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000220 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000221
222 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
223 return 0;
224
225 bgp->cluster_id.s_addr = 0;
226 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
227
228 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000229 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000230 {
231 if (peer_sort (peer) != BGP_PEER_IBGP)
232 continue;
233
234 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000235 {
236 peer->last_reset = PEER_DOWN_CLID_CHANGE;
237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
239 }
paul718e3742002-12-13 20:15:29 +0000240 }
241 return 0;
242}
243
244/* BGP timer configuration. */
245int
246bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
247{
248 bgp->default_keepalive = (keepalive < holdtime / 3
249 ? keepalive : holdtime / 3);
250 bgp->default_holdtime = holdtime;
251
252 return 0;
253}
254
255int
256bgp_timers_unset (struct bgp *bgp)
257{
258 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
259 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
260
261 return 0;
262}
263
264/* BGP confederation configuration. */
265int
266bgp_confederation_id_set (struct bgp *bgp, as_t as)
267{
268 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000269 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000270 int already_confed;
271
272 if (as == 0)
273 return BGP_ERR_INVALID_AS;
274
275 /* Remember - were we doing confederation before? */
276 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
277 bgp->confed_id = as;
278 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
279
280 /* If we were doing confederation already, this is just an external
281 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
282 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000283 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000284 {
285 /* We're looking for peers who's AS is not local or part of our
286 confederation. */
287 if (already_confed)
288 {
289 if (peer_sort (peer) == BGP_PEER_EBGP)
290 {
291 peer->local_as = as;
292 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000293 {
294 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
295 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
297 }
298
paul718e3742002-12-13 20:15:29 +0000299 else
300 BGP_EVENT_ADD (peer, BGP_Stop);
301 }
302 }
303 else
304 {
305 /* Not doign confederation before, so reset every non-local
306 session */
307 if (peer_sort (peer) != BGP_PEER_IBGP)
308 {
309 /* Reset the local_as to be our EBGP one */
310 if (peer_sort (peer) == BGP_PEER_EBGP)
311 peer->local_as = as;
312 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000313 {
314 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
315 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
316 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
317 }
paul718e3742002-12-13 20:15:29 +0000318 else
319 BGP_EVENT_ADD (peer, BGP_Stop);
320 }
321 }
322 }
323 return 0;
324}
325
326int
327bgp_confederation_id_unset (struct bgp *bgp)
328{
329 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000331
332 bgp->confed_id = 0;
333 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
334
paul1eb8ef22005-04-07 07:30:20 +0000335 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000336 {
337 /* We're looking for peers who's AS is not local */
338 if (peer_sort (peer) != BGP_PEER_IBGP)
339 {
340 peer->local_as = bgp->as;
341 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000342 {
343 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
344 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
345 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
346 }
347
paul718e3742002-12-13 20:15:29 +0000348 else
349 BGP_EVENT_ADD (peer, BGP_Stop);
350 }
351 }
352 return 0;
353}
354
355/* Is an AS part of the confed or not? */
356int
357bgp_confederation_peers_check (struct bgp *bgp, as_t as)
358{
359 int i;
360
361 if (! bgp)
362 return 0;
363
364 for (i = 0; i < bgp->confed_peers_cnt; i++)
365 if (bgp->confed_peers[i] == as)
366 return 1;
367
368 return 0;
369}
370
371/* Add an AS to the confederation set. */
372int
373bgp_confederation_peers_add (struct bgp *bgp, as_t as)
374{
375 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000376 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000377
378 if (! bgp)
379 return BGP_ERR_INVALID_BGP;
380
381 if (bgp->as == as)
382 return BGP_ERR_INVALID_AS;
383
384 if (bgp_confederation_peers_check (bgp, as))
385 return -1;
386
387 if (bgp->confed_peers)
388 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
389 bgp->confed_peers,
390 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
391 else
392 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
393 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
394
395 bgp->confed_peers[bgp->confed_peers_cnt] = as;
396 bgp->confed_peers_cnt++;
397
398 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
399 {
paul1eb8ef22005-04-07 07:30:20 +0000400 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000401 {
402 if (peer->as == as)
403 {
404 peer->local_as = bgp->as;
405 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000406 {
407 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
408 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
409 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
410 }
paul718e3742002-12-13 20:15:29 +0000411 else
412 BGP_EVENT_ADD (peer, BGP_Stop);
413 }
414 }
415 }
416 return 0;
417}
418
419/* Delete an AS from the confederation set. */
420int
421bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
422{
423 int i;
424 int j;
425 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000426 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000427
428 if (! bgp)
429 return -1;
430
431 if (! bgp_confederation_peers_check (bgp, as))
432 return -1;
433
434 for (i = 0; i < bgp->confed_peers_cnt; i++)
435 if (bgp->confed_peers[i] == as)
436 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
437 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
438
439 bgp->confed_peers_cnt--;
440
441 if (bgp->confed_peers_cnt == 0)
442 {
443 if (bgp->confed_peers)
444 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
445 bgp->confed_peers = NULL;
446 }
447 else
448 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
449 bgp->confed_peers,
450 bgp->confed_peers_cnt * sizeof (as_t));
451
452 /* Now reset any peer who's remote AS has just been removed from the
453 CONFED */
454 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
455 {
paul1eb8ef22005-04-07 07:30:20 +0000456 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000457 {
458 if (peer->as == as)
459 {
460 peer->local_as = bgp->confed_id;
461 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000462 {
463 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
466 }
paul718e3742002-12-13 20:15:29 +0000467 else
468 BGP_EVENT_ADD (peer, BGP_Stop);
469 }
470 }
471 }
472
473 return 0;
474}
475
476/* Local preference configuration. */
477int
478bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
479{
480 if (! bgp)
481 return -1;
482
paul718e3742002-12-13 20:15:29 +0000483 bgp->default_local_pref = local_pref;
484
485 return 0;
486}
487
488int
489bgp_default_local_preference_unset (struct bgp *bgp)
490{
491 if (! bgp)
492 return -1;
493
paul718e3742002-12-13 20:15:29 +0000494 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
495
496 return 0;
497}
498
paulfee0f4c2004-09-13 05:12:46 +0000499/* If peer is RSERVER_CLIENT in at least one address family and is not member
500 of a peer_group for that family, return 1.
501 Used to check wether the peer is included in list bgp->rsclient. */
502int
503peer_rsclient_active (struct peer *peer)
504{
505 int i;
506 int j;
507
508 for (i=AFI_IP; i < AFI_MAX; i++)
509 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
510 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
511 && ! peer->af_group[i][j])
512 return 1;
513 return 0;
514}
515
pauleb821182004-05-01 08:44:08 +0000516/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000517static int
518peer_cmp (struct peer *p1, struct peer *p2)
519{
pauleb821182004-05-01 08:44:08 +0000520 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000521}
522
523int
524peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
525{
526 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
527}
528
529/* Reset all address family specific configuration. */
530static void
531peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
532{
533 int i;
534 struct bgp_filter *filter;
535 char orf_name[BUFSIZ];
536
537 filter = &peer->filter[afi][safi];
538
539 /* Clear neighbor filter and route-map */
540 for (i = FILTER_IN; i < FILTER_MAX; i++)
541 {
542 if (filter->dlist[i].name)
543 {
544 free (filter->dlist[i].name);
545 filter->dlist[i].name = NULL;
546 }
547 if (filter->plist[i].name)
548 {
549 free (filter->plist[i].name);
550 filter->plist[i].name = NULL;
551 }
552 if (filter->aslist[i].name)
553 {
554 free (filter->aslist[i].name);
555 filter->aslist[i].name = NULL;
556 }
paulfee0f4c2004-09-13 05:12:46 +0000557 }
558 for (i = RMAP_IN; i < RMAP_MAX; i++)
559 {
paul718e3742002-12-13 20:15:29 +0000560 if (filter->map[i].name)
561 {
562 free (filter->map[i].name);
563 filter->map[i].name = NULL;
564 }
565 }
566
567 /* Clear unsuppress map. */
568 if (filter->usmap.name)
569 free (filter->usmap.name);
570 filter->usmap.name = NULL;
571 filter->usmap.map = NULL;
572
573 /* Clear neighbor's all address family flags. */
574 peer->af_flags[afi][safi] = 0;
575
576 /* Clear neighbor's all address family sflags. */
577 peer->af_sflags[afi][safi] = 0;
578
579 /* Clear neighbor's all address family capabilities. */
580 peer->af_cap[afi][safi] = 0;
581
582 /* Clear ORF info */
583 peer->orf_plist[afi][safi] = NULL;
584 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
585 prefix_bgp_orf_remove_all (orf_name);
586
587 /* Set default neighbor send-community. */
588 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
589 {
590 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
592 }
593
594 /* Clear neighbor default_originate_rmap */
595 if (peer->default_rmap[afi][safi].name)
596 free (peer->default_rmap[afi][safi].name);
597 peer->default_rmap[afi][safi].name = NULL;
598 peer->default_rmap[afi][safi].map = NULL;
599
600 /* Clear neighbor maximum-prefix */
601 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000602 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000603}
604
605/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000606static void
paul718e3742002-12-13 20:15:29 +0000607peer_global_config_reset (struct peer *peer)
608{
609 peer->weight = 0;
610 peer->change_local_as = 0;
611 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
612 if (peer->update_source)
613 {
614 sockunion_free (peer->update_source);
615 peer->update_source = NULL;
616 }
617 if (peer->update_if)
618 {
619 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
620 peer->update_if = NULL;
621 }
622
623 if (peer_sort (peer) == BGP_PEER_IBGP)
624 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
625 else
626 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
627
628 peer->flags = 0;
629 peer->config = 0;
630 peer->holdtime = 0;
631 peer->keepalive = 0;
632 peer->connect = 0;
633 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
634}
635
636/* Check peer's AS number and determin is this peer IBGP or EBGP */
637int
638peer_sort (struct peer *peer)
639{
640 struct bgp *bgp;
641
642 bgp = peer->bgp;
643
644 /* Peer-group */
645 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
646 {
647 if (peer->as)
648 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
649 else
650 {
651 struct peer *peer1;
652 peer1 = listnode_head (peer->group->peer);
653 if (peer1)
654 return (peer1->local_as == peer1->as
655 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
656 }
657 return BGP_PEER_INTERNAL;
658 }
659
660 /* Normal peer */
661 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
662 {
663 if (peer->local_as == 0)
664 return BGP_PEER_INTERNAL;
665
666 if (peer->local_as == peer->as)
667 {
668 if (peer->local_as == bgp->confed_id)
669 return BGP_PEER_EBGP;
670 else
671 return BGP_PEER_IBGP;
672 }
673
674 if (bgp_confederation_peers_check (bgp, peer->as))
675 return BGP_PEER_CONFED;
676
677 return BGP_PEER_EBGP;
678 }
679 else
680 {
681 return (peer->local_as == 0
682 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
683 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
684 }
685}
686
paul200df112005-06-01 11:17:05 +0000687static inline void
688peer_free (struct peer *peer)
689{
Paul Jakmaca058a32006-09-14 02:58:49 +0000690 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700691
692 bgp_unlock(peer->bgp);
693
Paul Jakmaca058a32006-09-14 02:58:49 +0000694 /* this /ought/ to have been done already through bgp_stop earlier,
695 * but just to be sure..
696 */
697 bgp_timer_set (peer);
698 BGP_READ_OFF (peer->t_read);
699 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000700 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000701
paul200df112005-06-01 11:17:05 +0000702 if (peer->desc)
703 XFREE (MTYPE_PEER_DESC, peer->desc);
704
705 /* Free allocated host character. */
706 if (peer->host)
707 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
708
709 /* Update source configuration. */
710 if (peer->update_source)
711 sockunion_free (peer->update_source);
712
713 if (peer->update_if)
714 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000715
716 if (peer->clear_node_queue)
717 work_queue_free (peer->clear_node_queue);
718
Paul Jakmaca058a32006-09-14 02:58:49 +0000719 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000720 memset (peer, 0, sizeof (struct peer));
721
722 XFREE (MTYPE_BGP_PEER, peer);
723}
724
725/* increase reference count on a struct peer */
726struct peer *
727peer_lock (struct peer *peer)
728{
729 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000730
paul200df112005-06-01 11:17:05 +0000731 peer->lock++;
732
733 return peer;
734}
735
736/* decrease reference count on a struct peer
737 * struct peer is freed and NULL returned if last reference
738 */
739struct peer *
740peer_unlock (struct peer *peer)
741{
742 assert (peer && (peer->lock > 0));
743
744 peer->lock--;
745
746 if (peer->lock == 0)
747 {
748#if 0
749 zlog_debug ("unlocked and freeing");
750 zlog_backtrace (LOG_DEBUG);
751#endif
752 peer_free (peer);
753 return NULL;
754 }
755
756#if 0
757 if (peer->lock == 1)
758 {
759 zlog_debug ("unlocked to 1");
760 zlog_backtrace (LOG_DEBUG);
761 }
762#endif
763
764 return peer;
765}
766
767/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000768static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000769peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000770{
771 afi_t afi;
772 safi_t safi;
773 struct peer *peer;
774 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000775
776 /* bgp argument is absolutely required */
777 assert (bgp);
778 if (!bgp)
779 return NULL;
780
paul718e3742002-12-13 20:15:29 +0000781 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000782 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000783
784 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000785 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000786 peer->v_start = BGP_INIT_START_TIMER;
787 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
788 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
789 peer->status = Idle;
790 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000791 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000792 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000793 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000794 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700795 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000796
797 /* Set default flags. */
798 for (afi = AFI_IP; afi < AFI_MAX; afi++)
799 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
800 {
801 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
802 {
803 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
804 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
805 }
806 peer->orf_plist[afi][safi] = NULL;
807 }
808 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
809
810 /* Create buffers. */
811 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
812 peer->obuf = stream_fifo_new ();
813 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
814
815 bgp_sync_init (peer);
816
817 /* Get service port number. */
818 sp = getservbyname ("bgp", "tcp");
819 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
820
821 return peer;
822}
823
824/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000825static struct peer *
paul718e3742002-12-13 20:15:29 +0000826peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
827 as_t remote_as, afi_t afi, safi_t safi)
828{
829 int active;
830 struct peer *peer;
831 char buf[SU_ADDRSTRLEN];
832
Paul Jakma6f585442006-10-22 19:13:07 +0000833 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000834 peer->su = *su;
835 peer->local_as = local_as;
836 peer->as = remote_as;
837 peer->local_id = bgp->router_id;
838 peer->v_holdtime = bgp->default_holdtime;
839 peer->v_keepalive = bgp->default_keepalive;
840 if (peer_sort (peer) == BGP_PEER_IBGP)
841 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
842 else
843 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000844
845 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000846 listnode_add_sort (bgp->peer, peer);
847
848 active = peer_active (peer);
849
850 if (afi && safi)
851 peer->afc[afi][safi] = 1;
852
853 /* Last read time set */
854 peer->readtime = time (NULL);
855
paul848973c2003-08-13 00:32:49 +0000856 /* Last reset time set */
857 peer->resettime = time (NULL);
858
paul718e3742002-12-13 20:15:29 +0000859 /* Default TTL set. */
860 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
861
862 /* Make peer's address string. */
863 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000864 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000865
866 /* Set up peer's events and timers. */
867 if (! active && peer_active (peer))
868 bgp_timer_set (peer);
869
870 return peer;
871}
872
pauleb821182004-05-01 08:44:08 +0000873/* Make accept BGP peer. Called from bgp_accept (). */
874struct peer *
875peer_create_accept (struct bgp *bgp)
876{
877 struct peer *peer;
878
Paul Jakma6f585442006-10-22 19:13:07 +0000879 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000880
881 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000882 listnode_add_sort (bgp->peer, peer);
883
884 return peer;
885}
886
paul718e3742002-12-13 20:15:29 +0000887/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000888static void
paul718e3742002-12-13 20:15:29 +0000889peer_as_change (struct peer *peer, as_t as)
890{
891 int type;
892
893 /* Stop peer. */
894 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
895 {
896 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000897 {
898 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
901 }
paul718e3742002-12-13 20:15:29 +0000902 else
903 BGP_EVENT_ADD (peer, BGP_Stop);
904 }
905 type = peer_sort (peer);
906 peer->as = as;
907
paul848973c2003-08-13 00:32:49 +0000908 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
909 && ! bgp_confederation_peers_check (peer->bgp, as)
910 && peer->bgp->as != as)
911 peer->local_as = peer->bgp->confed_id;
912 else
913 peer->local_as = peer->bgp->as;
914
paul718e3742002-12-13 20:15:29 +0000915 /* Advertisement-interval reset */
916 if (peer_sort (peer) == BGP_PEER_IBGP)
917 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
918 else
919 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
920
921 /* TTL reset */
922 if (peer_sort (peer) == BGP_PEER_IBGP)
923 peer->ttl = 255;
924 else if (type == BGP_PEER_IBGP)
925 peer->ttl = 1;
926
927 /* reflector-client reset */
928 if (peer_sort (peer) != BGP_PEER_IBGP)
929 {
930 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
931 PEER_FLAG_REFLECTOR_CLIENT);
932 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
933 PEER_FLAG_REFLECTOR_CLIENT);
934 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
935 PEER_FLAG_REFLECTOR_CLIENT);
936 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
937 PEER_FLAG_REFLECTOR_CLIENT);
938 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
939 PEER_FLAG_REFLECTOR_CLIENT);
940 }
941
942 /* local-as reset */
943 if (peer_sort (peer) != BGP_PEER_EBGP)
944 {
945 peer->change_local_as = 0;
946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
947 }
948}
949
950/* If peer does not exist, create new one. If peer already exists,
951 set AS number to the peer. */
952int
953peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
954 afi_t afi, safi_t safi)
955{
956 struct peer *peer;
957 as_t local_as;
958
959 peer = peer_lookup (bgp, su);
960
961 if (peer)
962 {
963 /* When this peer is a member of peer-group. */
964 if (peer->group)
965 {
966 if (peer->group->conf->as)
967 {
968 /* Return peer group's AS number. */
969 *as = peer->group->conf->as;
970 return BGP_ERR_PEER_GROUP_MEMBER;
971 }
972 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
973 {
974 if (bgp->as != *as)
975 {
976 *as = peer->as;
977 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
978 }
979 }
980 else
981 {
982 if (bgp->as == *as)
983 {
984 *as = peer->as;
985 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
986 }
987 }
988 }
989
990 /* Existing peer's AS number change. */
991 if (peer->as != *as)
992 peer_as_change (peer, *as);
993 }
994 else
995 {
996
997 /* If the peer is not part of our confederation, and its not an
998 iBGP peer then spoof the source AS */
999 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1000 && ! bgp_confederation_peers_check (bgp, *as)
1001 && bgp->as != *as)
1002 local_as = bgp->confed_id;
1003 else
1004 local_as = bgp->as;
1005
1006 /* If this is IPv4 unicast configuration and "no bgp default
1007 ipv4-unicast" is specified. */
1008
1009 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1010 && afi == AFI_IP && safi == SAFI_UNICAST)
1011 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1012 else
1013 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1014 }
1015
1016 return 0;
1017}
1018
1019/* Activate the peer or peer group for specified AFI and SAFI. */
1020int
1021peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1022{
1023 int active;
1024
1025 if (peer->afc[afi][safi])
1026 return 0;
1027
1028 /* Activate the address family configuration. */
1029 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1030 peer->afc[afi][safi] = 1;
1031 else
1032 {
1033 active = peer_active (peer);
1034
1035 peer->afc[afi][safi] = 1;
1036
1037 if (! active && peer_active (peer))
1038 bgp_timer_set (peer);
1039 else
1040 {
1041 if (peer->status == Established)
1042 {
1043 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1044 {
1045 peer->afc_adv[afi][safi] = 1;
1046 bgp_capability_send (peer, afi, safi,
1047 CAPABILITY_CODE_MP,
1048 CAPABILITY_ACTION_SET);
1049 if (peer->afc_recv[afi][safi])
1050 {
1051 peer->afc_nego[afi][safi] = 1;
1052 bgp_announce_route (peer, afi, safi);
1053 }
1054 }
1055 else
hassoe0701b72004-05-20 09:19:34 +00001056 {
1057 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1058 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1059 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1060 }
paul718e3742002-12-13 20:15:29 +00001061 }
1062 }
1063 }
1064 return 0;
1065}
1066
1067int
1068peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1069{
1070 struct peer_group *group;
1071 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001072 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001073
1074 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1075 {
1076 group = peer->group;
1077
paul1eb8ef22005-04-07 07:30:20 +00001078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001079 {
1080 if (peer1->af_group[afi][safi])
1081 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1082 }
1083 }
1084 else
1085 {
1086 if (peer->af_group[afi][safi])
1087 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1088 }
1089
1090 if (! peer->afc[afi][safi])
1091 return 0;
1092
1093 /* De-activate the address family configuration. */
1094 peer->afc[afi][safi] = 0;
1095 peer_af_flag_reset (peer, afi, safi);
1096
1097 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1098 {
1099 if (peer->status == Established)
1100 {
1101 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1102 {
1103 peer->afc_adv[afi][safi] = 0;
1104 peer->afc_nego[afi][safi] = 0;
1105
1106 if (peer_active_nego (peer))
1107 {
1108 bgp_capability_send (peer, afi, safi,
1109 CAPABILITY_CODE_MP,
1110 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001111 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001112 peer->pcount[afi][safi] = 0;
1113 }
1114 else
hassoe0701b72004-05-20 09:19:34 +00001115 {
1116 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1117 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1118 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1119 }
paul718e3742002-12-13 20:15:29 +00001120 }
1121 else
hassoe0701b72004-05-20 09:19:34 +00001122 {
1123 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1124 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1125 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1126 }
paul718e3742002-12-13 20:15:29 +00001127 }
1128 }
1129 return 0;
1130}
1131
hasso93406d82005-02-02 14:40:33 +00001132void
1133peer_nsf_stop (struct peer *peer)
1134{
1135 afi_t afi;
1136 safi_t safi;
1137
1138 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1139 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1140
1141 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1142 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1143 peer->nsf[afi][safi] = 0;
1144
1145 if (peer->t_gr_restart)
1146 {
1147 BGP_TIMER_OFF (peer->t_gr_restart);
1148 if (BGP_DEBUG (events, EVENTS))
1149 zlog_debug ("%s graceful restart timer stopped", peer->host);
1150 }
1151 if (peer->t_gr_stale)
1152 {
1153 BGP_TIMER_OFF (peer->t_gr_stale);
1154 if (BGP_DEBUG (events, EVENTS))
1155 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1156 }
1157 bgp_clear_route_all (peer);
1158}
1159
Paul Jakmaca058a32006-09-14 02:58:49 +00001160/* Delete peer from confguration.
1161 *
1162 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1163 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1164 *
1165 * This function /should/ take care to be idempotent, to guard against
1166 * it being called multiple times through stray events that come in
1167 * that happen to result in this function being called again. That
1168 * said, getting here for a "Deleted" peer is a bug in the neighbour
1169 * FSM.
1170 */
paul718e3742002-12-13 20:15:29 +00001171int
1172peer_delete (struct peer *peer)
1173{
1174 int i;
1175 afi_t afi;
1176 safi_t safi;
1177 struct bgp *bgp;
1178 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001179 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001180
Paul Jakmaca058a32006-09-14 02:58:49 +00001181 assert (peer->status != Deleted);
1182
paul718e3742002-12-13 20:15:29 +00001183 bgp = peer->bgp;
1184
hasso93406d82005-02-02 14:40:33 +00001185 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1186 peer_nsf_stop (peer);
1187
Chris Caputo228da422009-07-18 05:44:03 +00001188 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001189 relationship. */
1190 if (peer->group)
1191 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001192 if ((pn = listnode_lookup (peer->group->peer, peer)))
1193 {
1194 peer = peer_unlock (peer); /* group->peer list reference */
1195 list_delete_node (peer->group->peer, pn);
1196 }
paul718e3742002-12-13 20:15:29 +00001197 peer->group = NULL;
1198 }
paul200df112005-06-01 11:17:05 +00001199
paul718e3742002-12-13 20:15:29 +00001200 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001201 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1202 * executed after peer structure is deleted.
1203 */
hassoe0701b72004-05-20 09:19:34 +00001204 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001205 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001206 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001207
1208 /* Password configuration */
1209 if (peer->password)
1210 {
1211 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1212 peer->password = NULL;
1213
1214 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1215 bgp_md5_set (peer);
1216 }
1217
Paul Jakmaca058a32006-09-14 02:58:49 +00001218 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001221 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1222 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001223 {
Chris Caputo228da422009-07-18 05:44:03 +00001224 peer_unlock (peer); /* bgp peer list reference */
1225 list_delete_node (bgp->peer, pn);
1226 }
paul200df112005-06-01 11:17:05 +00001227
Chris Caputo228da422009-07-18 05:44:03 +00001228 if (peer_rsclient_active (peer)
1229 && (pn = listnode_lookup (bgp->rsclient, peer)))
1230 {
1231 peer_unlock (peer); /* rsclient list reference */
1232 list_delete_node (bgp->rsclient, pn);
1233
1234 /* Clear our own rsclient ribs. */
1235 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1236 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1237 if (CHECK_FLAG(peer->af_flags[afi][safi],
1238 PEER_FLAG_RSERVER_CLIENT))
1239 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001240 }
1241
1242 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1243 member of a peer_group. */
1244 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1245 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1246 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001247 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001248
paul200df112005-06-01 11:17:05 +00001249 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001250 if (peer->ibuf)
1251 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001252 if (peer->obuf)
1253 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001254 if (peer->work)
1255 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001256 peer->obuf = NULL;
1257 peer->work = peer->ibuf = NULL;
1258
paul718e3742002-12-13 20:15:29 +00001259 /* Local and remote addresses. */
1260 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001261 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001262 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001263 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001264 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001265
paul718e3742002-12-13 20:15:29 +00001266 /* Free filter related memory. */
1267 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1268 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1269 {
1270 filter = &peer->filter[afi][safi];
1271
1272 for (i = FILTER_IN; i < FILTER_MAX; i++)
1273 {
1274 if (filter->dlist[i].name)
1275 free (filter->dlist[i].name);
1276 if (filter->plist[i].name)
1277 free (filter->plist[i].name);
1278 if (filter->aslist[i].name)
1279 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001280
1281 filter->dlist[i].name = NULL;
1282 filter->plist[i].name = NULL;
1283 filter->aslist[i].name = NULL;
1284 }
1285 for (i = RMAP_IN; i < RMAP_MAX; i++)
1286 {
paul718e3742002-12-13 20:15:29 +00001287 if (filter->map[i].name)
1288 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001289 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001290 }
1291
1292 if (filter->usmap.name)
1293 free (filter->usmap.name);
1294
1295 if (peer->default_rmap[afi][safi].name)
1296 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001297
1298 filter->usmap.name = NULL;
1299 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001300 }
paul200df112005-06-01 11:17:05 +00001301
1302 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001303
1304 return 0;
1305}
1306
paul94f2b392005-06-28 12:44:16 +00001307static int
paul718e3742002-12-13 20:15:29 +00001308peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1309{
1310 return strcmp (g1->name, g2->name);
1311}
1312
1313/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001314static int
paul718e3742002-12-13 20:15:29 +00001315peer_group_active (struct peer *peer)
1316{
1317 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1318 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1319 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1320 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1321 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1322 return 1;
1323 return 0;
1324}
1325
1326/* Peer group cofiguration. */
1327static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001328peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001329{
1330 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1331 sizeof (struct peer_group));
1332}
1333
paul94f2b392005-06-28 12:44:16 +00001334static void
paul718e3742002-12-13 20:15:29 +00001335peer_group_free (struct peer_group *group)
1336{
1337 XFREE (MTYPE_PEER_GROUP, group);
1338}
1339
1340struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001341peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001342{
1343 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001344 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001345
paul1eb8ef22005-04-07 07:30:20 +00001346 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001347 {
1348 if (strcmp (group->name, name) == 0)
1349 return group;
1350 }
1351 return NULL;
1352}
1353
1354struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001355peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001356{
1357 struct peer_group *group;
1358
1359 group = peer_group_lookup (bgp, name);
1360 if (group)
1361 return group;
1362
1363 group = peer_group_new ();
1364 group->bgp = bgp;
1365 group->name = strdup (name);
1366 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001367 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001368 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1369 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001370 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001371 group->conf->group = group;
1372 group->conf->as = 0;
1373 group->conf->ttl = 1;
1374 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1375 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1376 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1377 group->conf->keepalive = 0;
1378 group->conf->holdtime = 0;
1379 group->conf->connect = 0;
1380 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1381 listnode_add_sort (bgp->group, group);
1382
1383 return 0;
1384}
1385
paul94f2b392005-06-28 12:44:16 +00001386static void
paul718e3742002-12-13 20:15:29 +00001387peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1388 afi_t afi, safi_t safi)
1389{
1390 int in = FILTER_IN;
1391 int out = FILTER_OUT;
1392 struct peer *conf;
1393 struct bgp_filter *pfilter;
1394 struct bgp_filter *gfilter;
1395
1396 conf = group->conf;
1397 pfilter = &peer->filter[afi][safi];
1398 gfilter = &conf->filter[afi][safi];
1399
1400 /* remote-as */
1401 if (conf->as)
1402 peer->as = conf->as;
1403
1404 /* remote-as */
1405 if (conf->change_local_as)
1406 peer->change_local_as = conf->change_local_as;
1407
1408 /* TTL */
1409 peer->ttl = conf->ttl;
1410
1411 /* Weight */
1412 peer->weight = conf->weight;
1413
1414 /* peer flags apply */
1415 peer->flags = conf->flags;
1416 /* peer af_flags apply */
1417 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1418 /* peer config apply */
1419 peer->config = conf->config;
1420
1421 /* peer timers apply */
1422 peer->holdtime = conf->holdtime;
1423 peer->keepalive = conf->keepalive;
1424 peer->connect = conf->connect;
1425 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1426 peer->v_connect = conf->connect;
1427 else
1428 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1429
1430 /* advertisement-interval reset */
1431 if (peer_sort (peer) == BGP_PEER_IBGP)
1432 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1433 else
1434 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1435
Paul Jakma0df7c912008-07-21 21:02:49 +00001436 /* password apply */
1437 if (peer->password)
1438 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1439
1440 if (conf->password)
1441 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1442 else
1443 peer->password = NULL;
1444
1445 bgp_md5_set (peer);
1446
paul718e3742002-12-13 20:15:29 +00001447 /* maximum-prefix */
1448 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001449 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001450 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001451
1452 /* allowas-in */
1453 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1454
paulfee0f4c2004-09-13 05:12:46 +00001455 /* route-server-client */
1456 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1457 {
1458 /* Make peer's RIB point to group's RIB. */
1459 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1460
1461 /* Import policy. */
1462 if (pfilter->map[RMAP_IMPORT].name)
1463 free (pfilter->map[RMAP_IMPORT].name);
1464 if (gfilter->map[RMAP_IMPORT].name)
1465 {
1466 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1467 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1468 }
1469 else
1470 {
1471 pfilter->map[RMAP_IMPORT].name = NULL;
1472 pfilter->map[RMAP_IMPORT].map = NULL;
1473 }
1474
1475 /* Export policy. */
1476 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1477 {
1478 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1479 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1480 }
1481 }
1482
paul718e3742002-12-13 20:15:29 +00001483 /* default-originate route-map */
1484 if (conf->default_rmap[afi][safi].name)
1485 {
1486 if (peer->default_rmap[afi][safi].name)
1487 free (peer->default_rmap[afi][safi].name);
1488 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1489 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1490 }
1491
1492 /* update-source apply */
1493 if (conf->update_source)
1494 {
1495 if (peer->update_source)
1496 sockunion_free (peer->update_source);
1497 if (peer->update_if)
1498 {
1499 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1500 peer->update_if = NULL;
1501 }
1502 peer->update_source = sockunion_dup (conf->update_source);
1503 }
1504 else if (conf->update_if)
1505 {
1506 if (peer->update_if)
1507 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1508 if (peer->update_source)
1509 {
1510 sockunion_free (peer->update_source);
1511 peer->update_source = NULL;
1512 }
1513 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1514 }
1515
1516 /* inbound filter apply */
1517 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1518 {
1519 if (pfilter->dlist[in].name)
1520 free (pfilter->dlist[in].name);
1521 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1522 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1523 }
1524 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1525 {
1526 if (pfilter->plist[in].name)
1527 free (pfilter->plist[in].name);
1528 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1529 pfilter->plist[in].plist = gfilter->plist[in].plist;
1530 }
1531 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1532 {
1533 if (pfilter->aslist[in].name)
1534 free (pfilter->aslist[in].name);
1535 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1536 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1537 }
paulfee0f4c2004-09-13 05:12:46 +00001538 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001539 {
paulfee0f4c2004-09-13 05:12:46 +00001540 if (pfilter->map[RMAP_IN].name)
1541 free (pfilter->map[RMAP_IN].name);
1542 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1543 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001544 }
1545
1546 /* outbound filter apply */
1547 if (gfilter->dlist[out].name)
1548 {
1549 if (pfilter->dlist[out].name)
1550 free (pfilter->dlist[out].name);
1551 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1552 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1553 }
1554 else
1555 {
1556 if (pfilter->dlist[out].name)
1557 free (pfilter->dlist[out].name);
1558 pfilter->dlist[out].name = NULL;
1559 pfilter->dlist[out].alist = NULL;
1560 }
1561 if (gfilter->plist[out].name)
1562 {
1563 if (pfilter->plist[out].name)
1564 free (pfilter->plist[out].name);
1565 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1566 pfilter->plist[out].plist = gfilter->plist[out].plist;
1567 }
1568 else
1569 {
1570 if (pfilter->plist[out].name)
1571 free (pfilter->plist[out].name);
1572 pfilter->plist[out].name = NULL;
1573 pfilter->plist[out].plist = NULL;
1574 }
1575 if (gfilter->aslist[out].name)
1576 {
1577 if (pfilter->aslist[out].name)
1578 free (pfilter->aslist[out].name);
1579 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1580 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1581 }
1582 else
1583 {
1584 if (pfilter->aslist[out].name)
1585 free (pfilter->aslist[out].name);
1586 pfilter->aslist[out].name = NULL;
1587 pfilter->aslist[out].aslist = NULL;
1588 }
paulfee0f4c2004-09-13 05:12:46 +00001589 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001590 {
paulfee0f4c2004-09-13 05:12:46 +00001591 if (pfilter->map[RMAP_OUT].name)
1592 free (pfilter->map[RMAP_OUT].name);
1593 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1594 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001595 }
1596 else
1597 {
paulfee0f4c2004-09-13 05:12:46 +00001598 if (pfilter->map[RMAP_OUT].name)
1599 free (pfilter->map[RMAP_OUT].name);
1600 pfilter->map[RMAP_OUT].name = NULL;
1601 pfilter->map[RMAP_OUT].map = NULL;
1602 }
1603
1604 /* RS-client's import/export route-maps. */
1605 if (gfilter->map[RMAP_IMPORT].name)
1606 {
1607 if (pfilter->map[RMAP_IMPORT].name)
1608 free (pfilter->map[RMAP_IMPORT].name);
1609 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1610 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1611 }
1612 else
1613 {
1614 if (pfilter->map[RMAP_IMPORT].name)
1615 free (pfilter->map[RMAP_IMPORT].name);
1616 pfilter->map[RMAP_IMPORT].name = NULL;
1617 pfilter->map[RMAP_IMPORT].map = NULL;
1618 }
1619 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1620 {
1621 if (pfilter->map[RMAP_EXPORT].name)
1622 free (pfilter->map[RMAP_EXPORT].name);
1623 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1624 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001625 }
1626
1627 if (gfilter->usmap.name)
1628 {
1629 if (pfilter->usmap.name)
1630 free (pfilter->usmap.name);
1631 pfilter->usmap.name = strdup (gfilter->usmap.name);
1632 pfilter->usmap.map = gfilter->usmap.map;
1633 }
1634 else
1635 {
1636 if (pfilter->usmap.name)
1637 free (pfilter->usmap.name);
1638 pfilter->usmap.name = NULL;
1639 pfilter->usmap.map = NULL;
1640 }
1641}
1642
1643/* Peer group's remote AS configuration. */
1644int
paulfd79ac92004-10-13 05:06:08 +00001645peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001646{
1647 struct peer_group *group;
1648 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001649 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001650
1651 group = peer_group_lookup (bgp, group_name);
1652 if (! group)
1653 return -1;
1654
1655 if (group->conf->as == *as)
1656 return 0;
1657
1658 /* When we setup peer-group AS number all peer group member's AS
1659 number must be updated to same number. */
1660 peer_as_change (group->conf, *as);
1661
paul1eb8ef22005-04-07 07:30:20 +00001662 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001663 {
1664 if (peer->as != *as)
1665 peer_as_change (peer, *as);
1666 }
1667
1668 return 0;
1669}
1670
1671int
1672peer_group_delete (struct peer_group *group)
1673{
1674 struct bgp *bgp;
1675 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001676 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001677
1678 bgp = group->bgp;
1679
paul1eb8ef22005-04-07 07:30:20 +00001680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001681 {
1682 peer->group = NULL;
1683 peer_delete (peer);
1684 }
1685 list_delete (group->peer);
1686
1687 free (group->name);
1688 group->name = NULL;
1689
1690 group->conf->group = NULL;
1691 peer_delete (group->conf);
1692
1693 /* Delete from all peer_group list. */
1694 listnode_delete (bgp->group, group);
1695
1696 peer_group_free (group);
1697
1698 return 0;
1699}
1700
1701int
1702peer_group_remote_as_delete (struct peer_group *group)
1703{
1704 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001705 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001706
1707 if (! group->conf->as)
1708 return 0;
1709
paul1eb8ef22005-04-07 07:30:20 +00001710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001711 {
1712 peer->group = NULL;
1713 peer_delete (peer);
1714 }
1715 list_delete_all_node (group->peer);
1716
1717 group->conf->as = 0;
1718
1719 return 0;
1720}
1721
1722/* Bind specified peer to peer group. */
1723int
1724peer_group_bind (struct bgp *bgp, union sockunion *su,
1725 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1726{
1727 struct peer *peer;
1728 int first_member = 0;
1729
1730 /* Check peer group's address family. */
1731 if (! group->conf->afc[afi][safi])
1732 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1733
1734 /* Lookup the peer. */
1735 peer = peer_lookup (bgp, su);
1736
1737 /* Create a new peer. */
1738 if (! peer)
1739 {
1740 if (! group->conf->as)
1741 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1742
1743 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1744 peer->group = group;
1745 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001746
Paul Jakmaca058a32006-09-14 02:58:49 +00001747 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001748 listnode_add (group->peer, peer);
1749 peer_group2peer_config_copy (group, peer, afi, safi);
1750
1751 return 0;
1752 }
1753
1754 /* When the peer already belongs to peer group, check the consistency. */
1755 if (peer->af_group[afi][safi])
1756 {
1757 if (strcmp (peer->group->name, group->name) != 0)
1758 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1759
1760 return 0;
1761 }
1762
1763 /* Check current peer group configuration. */
1764 if (peer_group_active (peer)
1765 && strcmp (peer->group->name, group->name) != 0)
1766 return BGP_ERR_PEER_GROUP_MISMATCH;
1767
1768 if (! group->conf->as)
1769 {
1770 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1771 && peer_sort (group->conf) != peer_sort (peer))
1772 {
1773 if (as)
1774 *as = peer->as;
1775 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1776 }
1777
1778 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1779 first_member = 1;
1780 }
1781
1782 peer->af_group[afi][safi] = 1;
1783 peer->afc[afi][safi] = 1;
1784 if (! peer->group)
1785 {
1786 peer->group = group;
paul200df112005-06-01 11:17:05 +00001787
Paul Jakmaca058a32006-09-14 02:58:49 +00001788 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001789 listnode_add (group->peer, peer);
1790 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001791 else
1792 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001793
1794 if (first_member)
1795 {
1796 /* Advertisement-interval reset */
1797 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1798 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1799 else
1800 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1801
1802 /* ebgp-multihop reset */
1803 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1804 group->conf->ttl = 255;
1805
1806 /* local-as reset */
1807 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1808 {
1809 group->conf->change_local_as = 0;
1810 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1811 }
1812 }
paulfee0f4c2004-09-13 05:12:46 +00001813
1814 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1815 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001816 struct listnode *pn;
1817
paulfee0f4c2004-09-13 05:12:46 +00001818 /* If it's not configured as RSERVER_CLIENT in any other address
1819 family, without being member of a peer_group, remove it from
1820 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001821 if (! peer_rsclient_active (peer)
1822 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001823 {
1824 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001825 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001826
1827 /* Clear our own rsclient rib for this afi/safi. */
1828 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001829 }
paulfee0f4c2004-09-13 05:12:46 +00001830
Paul Jakmab608d5b2008-07-02 02:12:07 +00001831 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001832
1833 /* Import policy. */
1834 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1835 {
1836 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1837 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1838 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1839 }
1840
1841 /* Export policy. */
1842 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1843 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1844 {
1845 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1846 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1847 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1848 }
1849 }
1850
paul718e3742002-12-13 20:15:29 +00001851 peer_group2peer_config_copy (group, peer, afi, safi);
1852
1853 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001854 {
1855 peer->last_reset = PEER_DOWN_RMAP_BIND;
1856 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1857 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1858 }
paul718e3742002-12-13 20:15:29 +00001859 else
1860 BGP_EVENT_ADD (peer, BGP_Stop);
1861
1862 return 0;
1863}
1864
1865int
1866peer_group_unbind (struct bgp *bgp, struct peer *peer,
1867 struct peer_group *group, afi_t afi, safi_t safi)
1868{
1869 if (! peer->af_group[afi][safi])
1870 return 0;
1871
1872 if (group != peer->group)
1873 return BGP_ERR_PEER_GROUP_MISMATCH;
1874
1875 peer->af_group[afi][safi] = 0;
1876 peer->afc[afi][safi] = 0;
1877 peer_af_flag_reset (peer, afi, safi);
1878
paulfee0f4c2004-09-13 05:12:46 +00001879 if (peer->rib[afi][safi])
1880 peer->rib[afi][safi] = NULL;
1881
paul718e3742002-12-13 20:15:29 +00001882 if (! peer_group_active (peer))
1883 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001884 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001885 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001886 listnode_delete (group->peer, peer);
1887 peer->group = NULL;
1888 if (group->conf->as)
1889 {
1890 peer_delete (peer);
1891 return 0;
1892 }
1893 peer_global_config_reset (peer);
1894 }
1895
1896 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001897 {
1898 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1901 }
paul718e3742002-12-13 20:15:29 +00001902 else
1903 BGP_EVENT_ADD (peer, BGP_Stop);
1904
1905 return 0;
1906}
1907
1908/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001909static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001910bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001911{
1912 struct bgp *bgp;
1913 afi_t afi;
1914 safi_t safi;
1915
paul200df112005-06-01 11:17:05 +00001916 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1917 return NULL;
1918
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001919 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001920 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001921 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001922
1923 bgp->peer = list_new ();
1924 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1925
1926 bgp->group = list_new ();
1927 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1928
paulfee0f4c2004-09-13 05:12:46 +00001929 bgp->rsclient = list_new ();
1930 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1931
paul718e3742002-12-13 20:15:29 +00001932 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1933 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1934 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001935 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1936 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1937 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001938 }
1939
1940 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1941 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1942 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001943 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1944 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001945
1946 bgp->as = *as;
1947
1948 if (name)
1949 bgp->name = strdup (name);
1950
1951 return bgp;
1952}
1953
1954/* Return first entry of BGP. */
1955struct bgp *
paul94f2b392005-06-28 12:44:16 +00001956bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001957{
1958 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001959 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001960 return NULL;
1961}
1962
1963/* Lookup BGP entry. */
1964struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001965bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001966{
1967 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001968 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001969
paul1eb8ef22005-04-07 07:30:20 +00001970 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001971 if (bgp->as == as
1972 && ((bgp->name == NULL && name == NULL)
1973 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1974 return bgp;
1975 return NULL;
1976}
1977
1978/* Lookup BGP structure by view name. */
1979struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001980bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001981{
1982 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001984
paul1eb8ef22005-04-07 07:30:20 +00001985 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001986 if ((bgp->name == NULL && name == NULL)
1987 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1988 return bgp;
1989 return NULL;
1990}
1991
1992/* Called from VTY commands. */
1993int
paulfd79ac92004-10-13 05:06:08 +00001994bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001995{
1996 struct bgp *bgp;
1997
1998 /* Multiple instance check. */
1999 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2000 {
2001 if (name)
2002 bgp = bgp_lookup_by_name (name);
2003 else
2004 bgp = bgp_get_default ();
2005
2006 /* Already exists. */
2007 if (bgp)
2008 {
2009 if (bgp->as != *as)
2010 {
2011 *as = bgp->as;
2012 return BGP_ERR_INSTANCE_MISMATCH;
2013 }
2014 *bgp_val = bgp;
2015 return 0;
2016 }
2017 }
2018 else
2019 {
2020 /* BGP instance name can not be specified for single instance. */
2021 if (name)
2022 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2023
2024 /* Get default BGP structure if exists. */
2025 bgp = bgp_get_default ();
2026
2027 if (bgp)
2028 {
2029 if (bgp->as != *as)
2030 {
2031 *as = bgp->as;
2032 return BGP_ERR_AS_MISMATCH;
2033 }
2034 *bgp_val = bgp;
2035 return 0;
2036 }
2037 }
2038
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002039 /* Create BGP server socket, if first instance. */
2040 if (list_isempty(bm->bgp))
2041 {
2042 if (bgp_socket (bm->port, bm->address) < 0)
2043 return BGP_ERR_INVALID_VALUE;
2044 }
2045
paul718e3742002-12-13 20:15:29 +00002046 bgp = bgp_create (as, name);
2047 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002048 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002049 *bgp_val = bgp;
2050
2051 return 0;
2052}
2053
2054/* Delete BGP instance. */
2055int
2056bgp_delete (struct bgp *bgp)
2057{
2058 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002059 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002060 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002061 struct listnode *next;
2062 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002063 int i;
2064
2065 /* Delete static route. */
2066 bgp_static_delete (bgp);
2067
2068 /* Unset redistribution. */
2069 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2070 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2071 if (i != ZEBRA_ROUTE_BGP)
2072 bgp_redistribute_unset (bgp, afi, i);
2073
paul1eb8ef22005-04-07 07:30:20 +00002074 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2075 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002076
Chris Caputo228da422009-07-18 05:44:03 +00002077 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2078 peer_group_delete (group);
2079
2080 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002081
2082 if (bgp->peer_self) {
2083 peer_delete(bgp->peer_self);
2084 bgp->peer_self = NULL;
2085 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002086
2087 /* Remove visibility via the master list - there may however still be
2088 * routes to be processed still referencing the struct bgp.
2089 */
2090 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002091 if (list_isempty(bm->bgp))
2092 bgp_close ();
2093
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002094 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002095
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002096 return 0;
2097}
2098
2099static void bgp_free (struct bgp *);
2100
2101void
2102bgp_lock (struct bgp *bgp)
2103{
2104 ++bgp->lock;
2105}
2106
2107void
2108bgp_unlock(struct bgp *bgp)
2109{
Chris Caputo228da422009-07-18 05:44:03 +00002110 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002111 if (--bgp->lock == 0)
2112 bgp_free (bgp);
2113}
2114
2115static void
2116bgp_free (struct bgp *bgp)
2117{
2118 afi_t afi;
2119 safi_t safi;
2120
2121 list_delete (bgp->group);
2122 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002123 list_delete (bgp->rsclient);
2124
paul718e3742002-12-13 20:15:29 +00002125 if (bgp->name)
2126 free (bgp->name);
2127
2128 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2129 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2130 {
2131 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002132 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002133 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002134 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002135 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002136 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002137 }
2138 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002139}
2140
2141struct peer *
2142peer_lookup (struct bgp *bgp, union sockunion *su)
2143{
2144 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002145 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002146
2147 if (! bgp)
2148 bgp = bgp_get_default ();
2149
2150 if (! bgp)
2151 return NULL;
2152
paul1eb8ef22005-04-07 07:30:20 +00002153 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002154 {
pauleb821182004-05-01 08:44:08 +00002155 if (sockunion_same (&peer->su, su)
2156 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2157 return peer;
paul718e3742002-12-13 20:15:29 +00002158 }
2159 return NULL;
2160}
2161
2162struct peer *
2163peer_lookup_with_open (union sockunion *su, as_t remote_as,
2164 struct in_addr *remote_id, int *as)
2165{
2166 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002167 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002168 struct bgp *bgp;
2169
2170 bgp = bgp_get_default ();
2171 if (! bgp)
2172 return NULL;
2173
paul1eb8ef22005-04-07 07:30:20 +00002174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002175 {
pauleb821182004-05-01 08:44:08 +00002176 if (sockunion_same (&peer->su, su)
2177 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2178 {
2179 if (peer->as == remote_as
2180 && peer->remote_id.s_addr == remote_id->s_addr)
2181 return peer;
2182 if (peer->as == remote_as)
2183 *as = 1;
2184 }
paul718e3742002-12-13 20:15:29 +00002185 }
paul1eb8ef22005-04-07 07:30:20 +00002186 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002187 {
pauleb821182004-05-01 08:44:08 +00002188 if (sockunion_same (&peer->su, su)
2189 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2190 {
2191 if (peer->as == remote_as
2192 && peer->remote_id.s_addr == 0)
2193 return peer;
2194 if (peer->as == remote_as)
2195 *as = 1;
2196 }
paul718e3742002-12-13 20:15:29 +00002197 }
2198 return NULL;
2199}
2200
2201/* If peer is configured at least one address family return 1. */
2202int
2203peer_active (struct peer *peer)
2204{
2205 if (peer->afc[AFI_IP][SAFI_UNICAST]
2206 || peer->afc[AFI_IP][SAFI_MULTICAST]
2207 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2208 || peer->afc[AFI_IP6][SAFI_UNICAST]
2209 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2210 return 1;
2211 return 0;
2212}
2213
2214/* If peer is negotiated at least one address family return 1. */
2215int
2216peer_active_nego (struct peer *peer)
2217{
2218 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2219 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2220 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2221 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2222 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2223 return 1;
2224 return 0;
2225}
2226
2227/* peer_flag_change_type. */
2228enum peer_change_type
2229{
2230 peer_change_none,
2231 peer_change_reset,
2232 peer_change_reset_in,
2233 peer_change_reset_out,
2234};
2235
paul94f2b392005-06-28 12:44:16 +00002236static void
paul718e3742002-12-13 20:15:29 +00002237peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2238 enum peer_change_type type)
2239{
2240 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2241 return;
2242
2243 if (type == peer_change_reset)
2244 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2245 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2246 else if (type == peer_change_reset_in)
2247 {
2248 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2249 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2250 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2251 else
2252 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2253 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2254 }
2255 else if (type == peer_change_reset_out)
2256 bgp_announce_route (peer, afi, safi);
2257}
2258
2259struct peer_flag_action
2260{
2261 /* Peer's flag. */
2262 u_int32_t flag;
2263
2264 /* This flag can be set for peer-group member. */
2265 u_char not_for_member;
2266
2267 /* Action when the flag is changed. */
2268 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002269
2270 /* Peer down cause */
2271 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002272};
2273
Stephen Hemminger03621952009-07-21 16:27:20 -07002274static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002275 {
2276 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2277 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2278 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2279 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2280 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002281 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002282 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002283 { 0, 0, 0 }
2284 };
2285
Stephen Hemminger03621952009-07-21 16:27:20 -07002286static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002287 {
2288 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2289 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2290 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2291 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2292 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2293 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2294 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2295 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2296 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2297 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2298 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2299 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2300 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002301 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002302 { 0, 0, 0 }
2303 };
2304
2305/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002306static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002307peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002308 struct peer_flag_action *action, u_int32_t flag)
2309{
2310 int i;
2311 int found = 0;
2312 int reset_in = 0;
2313 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002314 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002315
2316 /* Check peer's frag action. */
2317 for (i = 0; i < size; i++)
2318 {
2319 match = &action_list[i];
2320
2321 if (match->flag == 0)
2322 break;
2323
2324 if (match->flag & flag)
2325 {
2326 found = 1;
2327
2328 if (match->type == peer_change_reset_in)
2329 reset_in = 1;
2330 if (match->type == peer_change_reset_out)
2331 reset_out = 1;
2332 if (match->type == peer_change_reset)
2333 {
2334 reset_in = 1;
2335 reset_out = 1;
2336 }
2337 if (match->not_for_member)
2338 action->not_for_member = 1;
2339 }
2340 }
2341
2342 /* Set peer clear type. */
2343 if (reset_in && reset_out)
2344 action->type = peer_change_reset;
2345 else if (reset_in)
2346 action->type = peer_change_reset_in;
2347 else if (reset_out)
2348 action->type = peer_change_reset_out;
2349 else
2350 action->type = peer_change_none;
2351
2352 return found;
2353}
2354
paul94f2b392005-06-28 12:44:16 +00002355static void
paul718e3742002-12-13 20:15:29 +00002356peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2357{
2358 if (flag == PEER_FLAG_SHUTDOWN)
2359 {
2360 if (CHECK_FLAG (peer->flags, flag))
2361 {
hasso93406d82005-02-02 14:40:33 +00002362 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2363 peer_nsf_stop (peer);
2364
hasso0a486e52005-02-01 20:57:17 +00002365 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2366 if (peer->t_pmax_restart)
2367 {
2368 BGP_TIMER_OFF (peer->t_pmax_restart);
2369 if (BGP_DEBUG (events, EVENTS))
2370 zlog_debug ("%s Maximum-prefix restart timer canceled",
2371 peer->host);
2372 }
2373
hasso93406d82005-02-02 14:40:33 +00002374 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2375 peer_nsf_stop (peer);
2376
paul718e3742002-12-13 20:15:29 +00002377 if (peer->status == Established)
2378 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2379 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2380 else
2381 BGP_EVENT_ADD (peer, BGP_Stop);
2382 }
2383 else
2384 {
2385 peer->v_start = BGP_INIT_START_TIMER;
2386 BGP_EVENT_ADD (peer, BGP_Stop);
2387 }
2388 }
2389 else if (peer->status == Established)
2390 {
hassoc9502432005-02-01 22:01:48 +00002391 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2392 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2393 else if (flag == PEER_FLAG_PASSIVE)
2394 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002395 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002396 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002397
hassoc9502432005-02-01 22:01:48 +00002398 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2399 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002400 }
2401 else
2402 BGP_EVENT_ADD (peer, BGP_Stop);
2403}
2404
2405/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002406static int
paul718e3742002-12-13 20:15:29 +00002407peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2408{
2409 int found;
2410 int size;
2411 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002412 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002413 struct peer_flag_action action;
2414
2415 memset (&action, 0, sizeof (struct peer_flag_action));
2416 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2417
2418 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2419
2420 /* No flag action is found. */
2421 if (! found)
2422 return BGP_ERR_INVALID_FLAG;
2423
2424 /* Not for peer-group member. */
2425 if (action.not_for_member && peer_group_active (peer))
2426 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2427
2428 /* When unset the peer-group member's flag we have to check
2429 peer-group configuration. */
2430 if (! set && peer_group_active (peer))
2431 if (CHECK_FLAG (peer->group->conf->flags, flag))
2432 {
2433 if (flag == PEER_FLAG_SHUTDOWN)
2434 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2435 else
2436 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2437 }
2438
2439 /* Flag conflict check. */
2440 if (set
2441 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2442 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2443 return BGP_ERR_PEER_FLAG_CONFLICT;
2444
2445 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2446 {
2447 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2448 return 0;
2449 if (! set && ! CHECK_FLAG (peer->flags, flag))
2450 return 0;
2451 }
2452
2453 if (set)
2454 SET_FLAG (peer->flags, flag);
2455 else
2456 UNSET_FLAG (peer->flags, flag);
2457
2458 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2459 {
2460 if (action.type == peer_change_reset)
2461 peer_flag_modify_action (peer, flag);
2462
2463 return 0;
2464 }
2465
2466 /* peer-group member updates. */
2467 group = peer->group;
2468
paul1eb8ef22005-04-07 07:30:20 +00002469 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002470 {
2471 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2472 continue;
2473
2474 if (! set && ! CHECK_FLAG (peer->flags, flag))
2475 continue;
2476
2477 if (set)
2478 SET_FLAG (peer->flags, flag);
2479 else
2480 UNSET_FLAG (peer->flags, flag);
2481
2482 if (action.type == peer_change_reset)
2483 peer_flag_modify_action (peer, flag);
2484 }
2485 return 0;
2486}
2487
2488int
2489peer_flag_set (struct peer *peer, u_int32_t flag)
2490{
2491 return peer_flag_modify (peer, flag, 1);
2492}
2493
2494int
2495peer_flag_unset (struct peer *peer, u_int32_t flag)
2496{
2497 return peer_flag_modify (peer, flag, 0);
2498}
2499
paul94f2b392005-06-28 12:44:16 +00002500static int
paul718e3742002-12-13 20:15:29 +00002501peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2502{
2503 if (peer->af_group[afi][safi])
2504 return 1;
2505 return 0;
2506}
2507
paul94f2b392005-06-28 12:44:16 +00002508static int
paul718e3742002-12-13 20:15:29 +00002509peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2510 int set)
2511{
2512 int found;
2513 int size;
paul1eb8ef22005-04-07 07:30:20 +00002514 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002515 struct peer_group *group;
2516 struct peer_flag_action action;
2517
2518 memset (&action, 0, sizeof (struct peer_flag_action));
2519 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2520
2521 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2522
2523 /* No flag action is found. */
2524 if (! found)
2525 return BGP_ERR_INVALID_FLAG;
2526
2527 /* Adress family must be activated. */
2528 if (! peer->afc[afi][safi])
2529 return BGP_ERR_PEER_INACTIVE;
2530
2531 /* Not for peer-group member. */
2532 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2533 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2534
2535 /* Spcecial check for reflector client. */
2536 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2537 && peer_sort (peer) != BGP_PEER_IBGP)
2538 return BGP_ERR_NOT_INTERNAL_PEER;
2539
2540 /* Spcecial check for remove-private-AS. */
2541 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2542 && peer_sort (peer) == BGP_PEER_IBGP)
2543 return BGP_ERR_REMOVE_PRIVATE_AS;
2544
2545 /* When unset the peer-group member's flag we have to check
2546 peer-group configuration. */
2547 if (! set && peer->af_group[afi][safi])
2548 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2549 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2550
2551 /* When current flag configuration is same as requested one. */
2552 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2553 {
2554 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2555 return 0;
2556 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2557 return 0;
2558 }
2559
2560 if (set)
2561 SET_FLAG (peer->af_flags[afi][safi], flag);
2562 else
2563 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2564
2565 /* Execute action when peer is established. */
2566 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2567 && peer->status == Established)
2568 {
2569 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2570 bgp_clear_adj_in (peer, afi, safi);
2571 else
hassoe0701b72004-05-20 09:19:34 +00002572 {
2573 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2574 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2575 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2576 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2577 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2578 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2579 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2580 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2581
2582 peer_change_action (peer, afi, safi, action.type);
2583 }
2584
paul718e3742002-12-13 20:15:29 +00002585 }
2586
2587 /* Peer group member updates. */
2588 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2589 {
2590 group = peer->group;
2591
paul1eb8ef22005-04-07 07:30:20 +00002592 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002593 {
2594 if (! peer->af_group[afi][safi])
2595 continue;
2596
2597 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2598 continue;
2599
2600 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2601 continue;
2602
2603 if (set)
2604 SET_FLAG (peer->af_flags[afi][safi], flag);
2605 else
2606 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2607
2608 if (peer->status == Established)
2609 {
2610 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2611 bgp_clear_adj_in (peer, afi, safi);
2612 else
hassoe0701b72004-05-20 09:19:34 +00002613 {
2614 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2615 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2616 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2617 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2618 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2619 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2620 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2621 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2622
2623 peer_change_action (peer, afi, safi, action.type);
2624 }
paul718e3742002-12-13 20:15:29 +00002625 }
2626 }
2627 }
2628 return 0;
2629}
2630
2631int
2632peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2633{
2634 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2635}
2636
2637int
2638peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2639{
2640 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2641}
2642
2643/* EBGP multihop configuration. */
2644int
2645peer_ebgp_multihop_set (struct peer *peer, int ttl)
2646{
2647 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002648 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002649
2650 if (peer_sort (peer) == BGP_PEER_IBGP)
2651 return 0;
2652
2653 peer->ttl = ttl;
2654
2655 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2656 {
pauleb821182004-05-01 08:44:08 +00002657 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2658 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002659 }
2660 else
2661 {
2662 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002663 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002664 {
2665 if (peer_sort (peer) == BGP_PEER_IBGP)
2666 continue;
paul718e3742002-12-13 20:15:29 +00002667
pauleb821182004-05-01 08:44:08 +00002668 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002669
pauleb821182004-05-01 08:44:08 +00002670 if (peer->fd >= 0)
2671 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2672 }
paul718e3742002-12-13 20:15:29 +00002673 }
2674 return 0;
2675}
2676
2677int
2678peer_ebgp_multihop_unset (struct peer *peer)
2679{
2680 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002681 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002682
2683 if (peer_sort (peer) == BGP_PEER_IBGP)
2684 return 0;
2685
2686 if (peer_group_active (peer))
2687 peer->ttl = peer->group->conf->ttl;
2688 else
2689 peer->ttl = 1;
2690
2691 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2692 {
pauleb821182004-05-01 08:44:08 +00002693 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2694 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002695 }
2696 else
2697 {
2698 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002699 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002700 {
2701 if (peer_sort (peer) == BGP_PEER_IBGP)
2702 continue;
paul718e3742002-12-13 20:15:29 +00002703
pauleb821182004-05-01 08:44:08 +00002704 peer->ttl = 1;
2705
2706 if (peer->fd >= 0)
2707 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2708 }
paul718e3742002-12-13 20:15:29 +00002709 }
2710 return 0;
2711}
2712
2713/* Neighbor description. */
2714int
2715peer_description_set (struct peer *peer, char *desc)
2716{
2717 if (peer->desc)
2718 XFREE (MTYPE_PEER_DESC, peer->desc);
2719
2720 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2721
2722 return 0;
2723}
2724
2725int
2726peer_description_unset (struct peer *peer)
2727{
2728 if (peer->desc)
2729 XFREE (MTYPE_PEER_DESC, peer->desc);
2730
2731 peer->desc = NULL;
2732
2733 return 0;
2734}
2735
2736/* Neighbor update-source. */
2737int
paulfd79ac92004-10-13 05:06:08 +00002738peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002739{
2740 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002741 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002742
2743 if (peer->update_if)
2744 {
2745 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2746 && strcmp (peer->update_if, ifname) == 0)
2747 return 0;
2748
2749 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2750 peer->update_if = NULL;
2751 }
2752
2753 if (peer->update_source)
2754 {
2755 sockunion_free (peer->update_source);
2756 peer->update_source = NULL;
2757 }
2758
2759 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2760
2761 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2762 {
2763 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002764 {
2765 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2766 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2767 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2768 }
paul718e3742002-12-13 20:15:29 +00002769 else
2770 BGP_EVENT_ADD (peer, BGP_Stop);
2771 return 0;
2772 }
2773
2774 /* peer-group member updates. */
2775 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002776 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002777 {
2778 if (peer->update_if)
2779 {
2780 if (strcmp (peer->update_if, ifname) == 0)
2781 continue;
2782
2783 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2784 peer->update_if = NULL;
2785 }
2786
2787 if (peer->update_source)
2788 {
2789 sockunion_free (peer->update_source);
2790 peer->update_source = NULL;
2791 }
2792
2793 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2794
2795 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002796 {
2797 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2798 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2799 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2800 }
paul718e3742002-12-13 20:15:29 +00002801 else
2802 BGP_EVENT_ADD (peer, BGP_Stop);
2803 }
2804 return 0;
2805}
2806
2807int
2808peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2809{
2810 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002811 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002812
2813 if (peer->update_source)
2814 {
2815 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2816 && sockunion_cmp (peer->update_source, su) == 0)
2817 return 0;
2818 sockunion_free (peer->update_source);
2819 peer->update_source = NULL;
2820 }
2821
2822 if (peer->update_if)
2823 {
2824 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2825 peer->update_if = NULL;
2826 }
2827
2828 peer->update_source = sockunion_dup (su);
2829
2830 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2831 {
2832 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002833 {
2834 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2835 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2836 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2837 }
paul718e3742002-12-13 20:15:29 +00002838 else
2839 BGP_EVENT_ADD (peer, BGP_Stop);
2840 return 0;
2841 }
2842
2843 /* peer-group member updates. */
2844 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002845 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002846 {
2847 if (peer->update_source)
2848 {
2849 if (sockunion_cmp (peer->update_source, su) == 0)
2850 continue;
2851 sockunion_free (peer->update_source);
2852 peer->update_source = NULL;
2853 }
2854
2855 if (peer->update_if)
2856 {
2857 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2858 peer->update_if = NULL;
2859 }
2860
2861 peer->update_source = sockunion_dup (su);
2862
2863 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002864 {
2865 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2866 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2867 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2868 }
paul718e3742002-12-13 20:15:29 +00002869 else
2870 BGP_EVENT_ADD (peer, BGP_Stop);
2871 }
2872 return 0;
2873}
2874
2875int
2876peer_update_source_unset (struct peer *peer)
2877{
2878 union sockunion *su;
2879 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002880 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002881
2882 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2883 && ! peer->update_source
2884 && ! peer->update_if)
2885 return 0;
2886
2887 if (peer->update_source)
2888 {
2889 sockunion_free (peer->update_source);
2890 peer->update_source = NULL;
2891 }
2892 if (peer->update_if)
2893 {
2894 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2895 peer->update_if = NULL;
2896 }
2897
2898 if (peer_group_active (peer))
2899 {
2900 group = peer->group;
2901
2902 if (group->conf->update_source)
2903 {
2904 su = sockunion_dup (group->conf->update_source);
2905 peer->update_source = su;
2906 }
2907 else if (group->conf->update_if)
2908 peer->update_if =
2909 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2910 }
2911
2912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2913 {
2914 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002915 {
2916 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2917 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2918 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2919 }
paul718e3742002-12-13 20:15:29 +00002920 else
2921 BGP_EVENT_ADD (peer, BGP_Stop);
2922 return 0;
2923 }
2924
2925 /* peer-group member updates. */
2926 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002927 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002928 {
2929 if (! peer->update_source && ! peer->update_if)
2930 continue;
2931
2932 if (peer->update_source)
2933 {
2934 sockunion_free (peer->update_source);
2935 peer->update_source = NULL;
2936 }
2937
2938 if (peer->update_if)
2939 {
2940 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2941 peer->update_if = NULL;
2942 }
2943
2944 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002945 {
2946 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2947 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2948 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2949 }
paul718e3742002-12-13 20:15:29 +00002950 else
2951 BGP_EVENT_ADD (peer, BGP_Stop);
2952 }
2953 return 0;
2954}
2955
2956int
2957peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002958 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002959{
2960 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002961 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002962
2963 /* Adress family must be activated. */
2964 if (! peer->afc[afi][safi])
2965 return BGP_ERR_PEER_INACTIVE;
2966
2967 /* Default originate can't be used for peer group memeber. */
2968 if (peer_is_group_member (peer, afi, safi))
2969 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2970
2971 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2972 || (rmap && ! peer->default_rmap[afi][safi].name)
2973 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2974 {
2975 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2976
2977 if (rmap)
2978 {
2979 if (peer->default_rmap[afi][safi].name)
2980 free (peer->default_rmap[afi][safi].name);
2981 peer->default_rmap[afi][safi].name = strdup (rmap);
2982 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2983 }
2984 }
2985
2986 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2987 {
2988 if (peer->status == Established && peer->afc_nego[afi][safi])
2989 bgp_default_originate (peer, afi, safi, 0);
2990 return 0;
2991 }
2992
2993 /* peer-group member updates. */
2994 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002995 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002996 {
2997 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2998
2999 if (rmap)
3000 {
3001 if (peer->default_rmap[afi][safi].name)
3002 free (peer->default_rmap[afi][safi].name);
3003 peer->default_rmap[afi][safi].name = strdup (rmap);
3004 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3005 }
3006
3007 if (peer->status == Established && peer->afc_nego[afi][safi])
3008 bgp_default_originate (peer, afi, safi, 0);
3009 }
3010 return 0;
3011}
3012
3013int
3014peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3015{
3016 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003017 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003018
3019 /* Adress family must be activated. */
3020 if (! peer->afc[afi][safi])
3021 return BGP_ERR_PEER_INACTIVE;
3022
3023 /* Default originate can't be used for peer group memeber. */
3024 if (peer_is_group_member (peer, afi, safi))
3025 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3026
3027 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3028 {
3029 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3030
3031 if (peer->default_rmap[afi][safi].name)
3032 free (peer->default_rmap[afi][safi].name);
3033 peer->default_rmap[afi][safi].name = NULL;
3034 peer->default_rmap[afi][safi].map = NULL;
3035 }
3036
3037 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3038 {
3039 if (peer->status == Established && peer->afc_nego[afi][safi])
3040 bgp_default_originate (peer, afi, safi, 1);
3041 return 0;
3042 }
3043
3044 /* peer-group member updates. */
3045 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003046 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003047 {
3048 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3049
3050 if (peer->default_rmap[afi][safi].name)
3051 free (peer->default_rmap[afi][safi].name);
3052 peer->default_rmap[afi][safi].name = NULL;
3053 peer->default_rmap[afi][safi].map = NULL;
3054
3055 if (peer->status == Established && peer->afc_nego[afi][safi])
3056 bgp_default_originate (peer, afi, safi, 1);
3057 }
3058 return 0;
3059}
3060
3061int
3062peer_port_set (struct peer *peer, u_int16_t port)
3063{
3064 peer->port = port;
3065 return 0;
3066}
3067
3068int
3069peer_port_unset (struct peer *peer)
3070{
3071 peer->port = BGP_PORT_DEFAULT;
3072 return 0;
3073}
3074
3075/* neighbor weight. */
3076int
3077peer_weight_set (struct peer *peer, u_int16_t weight)
3078{
3079 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003080 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003081
3082 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3083 peer->weight = weight;
3084
3085 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3086 return 0;
3087
3088 /* peer-group member updates. */
3089 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003090 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003091 {
3092 peer->weight = group->conf->weight;
3093 }
3094 return 0;
3095}
3096
3097int
3098peer_weight_unset (struct peer *peer)
3099{
3100 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003101 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003102
3103 /* Set default weight. */
3104 if (peer_group_active (peer))
3105 peer->weight = peer->group->conf->weight;
3106 else
3107 peer->weight = 0;
3108
3109 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3110
3111 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3112 return 0;
3113
3114 /* peer-group member updates. */
3115 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003116 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003117 {
3118 peer->weight = 0;
3119 }
3120 return 0;
3121}
3122
3123int
3124peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3125{
3126 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003127 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003128
3129 /* Not for peer group memeber. */
3130 if (peer_group_active (peer))
3131 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3132
3133 /* keepalive value check. */
3134 if (keepalive > 65535)
3135 return BGP_ERR_INVALID_VALUE;
3136
3137 /* Holdtime value check. */
3138 if (holdtime > 65535)
3139 return BGP_ERR_INVALID_VALUE;
3140
3141 /* Holdtime value must be either 0 or greater than 3. */
3142 if (holdtime < 3 && holdtime != 0)
3143 return BGP_ERR_INVALID_VALUE;
3144
3145 /* Set value to the configuration. */
3146 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3147 peer->holdtime = holdtime;
3148 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3149
3150 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3151 return 0;
3152
3153 /* peer-group member updates. */
3154 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003155 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003156 {
3157 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3158 peer->holdtime = group->conf->holdtime;
3159 peer->keepalive = group->conf->keepalive;
3160 }
3161 return 0;
3162}
3163
3164int
3165peer_timers_unset (struct peer *peer)
3166{
3167 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003168 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003169
3170 if (peer_group_active (peer))
3171 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3172
3173 /* Clear configuration. */
3174 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3175 peer->keepalive = 0;
3176 peer->holdtime = 0;
3177
3178 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3179 return 0;
3180
3181 /* peer-group member updates. */
3182 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003183 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003184 {
3185 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3186 peer->holdtime = 0;
3187 peer->keepalive = 0;
3188 }
3189
3190 return 0;
3191}
3192
3193int
3194peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3195{
3196 if (peer_group_active (peer))
3197 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3198
3199 if (connect > 65535)
3200 return BGP_ERR_INVALID_VALUE;
3201
3202 /* Set value to the configuration. */
3203 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3204 peer->connect = connect;
3205
3206 /* Set value to timer setting. */
3207 peer->v_connect = connect;
3208
3209 return 0;
3210}
3211
3212int
3213peer_timers_connect_unset (struct peer *peer)
3214{
3215 if (peer_group_active (peer))
3216 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3217
3218 /* Clear configuration. */
3219 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3220 peer->connect = 0;
3221
3222 /* Set timer setting to default value. */
3223 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3224
3225 return 0;
3226}
3227
3228int
3229peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3230{
3231 if (peer_group_active (peer))
3232 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3233
3234 if (routeadv > 600)
3235 return BGP_ERR_INVALID_VALUE;
3236
3237 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3238 peer->routeadv = routeadv;
3239 peer->v_routeadv = routeadv;
3240
3241 return 0;
3242}
3243
3244int
3245peer_advertise_interval_unset (struct peer *peer)
3246{
3247 if (peer_group_active (peer))
3248 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3249
3250 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3251 peer->routeadv = 0;
3252
3253 if (peer_sort (peer) == BGP_PEER_IBGP)
3254 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3255 else
3256 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3257
3258 return 0;
3259}
3260
paul718e3742002-12-13 20:15:29 +00003261/* neighbor interface */
3262int
paulfd79ac92004-10-13 05:06:08 +00003263peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003264{
3265 if (peer->ifname)
3266 free (peer->ifname);
3267 peer->ifname = strdup (str);
3268
3269 return 0;
3270}
3271
3272int
3273peer_interface_unset (struct peer *peer)
3274{
3275 if (peer->ifname)
3276 free (peer->ifname);
3277 peer->ifname = NULL;
3278
3279 return 0;
3280}
3281
3282/* Allow-as in. */
3283int
3284peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3285{
3286 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003287 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003288
3289 if (allow_num < 1 || allow_num > 10)
3290 return BGP_ERR_INVALID_VALUE;
3291
3292 if (peer->allowas_in[afi][safi] != allow_num)
3293 {
3294 peer->allowas_in[afi][safi] = allow_num;
3295 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3296 peer_change_action (peer, afi, safi, peer_change_reset_in);
3297 }
3298
3299 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3300 return 0;
3301
3302 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003303 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003304 {
3305 if (peer->allowas_in[afi][safi] != allow_num)
3306 {
3307 peer->allowas_in[afi][safi] = allow_num;
3308 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3309 peer_change_action (peer, afi, safi, peer_change_reset_in);
3310 }
3311
3312 }
3313 return 0;
3314}
3315
3316int
3317peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3318{
3319 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003320 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003321
3322 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3323 {
3324 peer->allowas_in[afi][safi] = 0;
3325 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3326 }
3327
3328 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3329 return 0;
3330
3331 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003332 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003333 {
3334 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3335 {
3336 peer->allowas_in[afi][safi] = 0;
3337 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3338 }
3339 }
3340 return 0;
3341}
3342
3343int
3344peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3345{
3346 struct bgp *bgp = peer->bgp;
3347 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003348 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003349
3350 if (peer_sort (peer) != BGP_PEER_EBGP
3351 && peer_sort (peer) != BGP_PEER_INTERNAL)
3352 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3353
3354 if (bgp->as == as)
3355 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3356
3357 if (peer_group_active (peer))
3358 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3359
3360 if (peer->change_local_as == as &&
3361 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3362 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3363 return 0;
3364
3365 peer->change_local_as = as;
3366 if (no_prepend)
3367 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3368 else
3369 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3370
3371 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3372 {
3373 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003374 {
3375 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3376 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3377 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3378 }
paul718e3742002-12-13 20:15:29 +00003379 else
3380 BGP_EVENT_ADD (peer, BGP_Stop);
3381
3382 return 0;
3383 }
3384
3385 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003386 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003387 {
3388 peer->change_local_as = as;
3389 if (no_prepend)
3390 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3391 else
3392 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3393
3394 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003395 {
3396 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3397 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3398 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3399 }
paul718e3742002-12-13 20:15:29 +00003400 else
3401 BGP_EVENT_ADD (peer, BGP_Stop);
3402 }
3403
3404 return 0;
3405}
3406
3407int
3408peer_local_as_unset (struct peer *peer)
3409{
3410 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003411 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003412
3413 if (peer_group_active (peer))
3414 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3415
3416 if (! peer->change_local_as)
3417 return 0;
3418
3419 peer->change_local_as = 0;
3420 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3421
3422 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3423 {
3424 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003425 {
3426 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3427 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3428 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3429 }
paul718e3742002-12-13 20:15:29 +00003430 else
3431 BGP_EVENT_ADD (peer, BGP_Stop);
3432
3433 return 0;
3434 }
3435
3436 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003437 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003438 {
3439 peer->change_local_as = 0;
3440 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3441
3442 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003443 {
3444 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3445 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3446 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3447 }
paul718e3742002-12-13 20:15:29 +00003448 else
3449 BGP_EVENT_ADD (peer, BGP_Stop);
3450 }
3451 return 0;
3452}
3453
Paul Jakma0df7c912008-07-21 21:02:49 +00003454/* Set password for authenticating with the peer. */
3455int
3456peer_password_set (struct peer *peer, const char *password)
3457{
3458 struct listnode *nn, *nnode;
3459 int len = password ? strlen(password) : 0;
3460 int ret = BGP_SUCCESS;
3461
3462 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3463 return BGP_ERR_INVALID_VALUE;
3464
3465 if (peer->password && strcmp (peer->password, password) == 0
3466 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3467 return 0;
3468
3469 if (peer->password)
3470 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3471
3472 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3473
3474 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3475 {
3476 if (peer->status == Established)
3477 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3478 else
3479 BGP_EVENT_ADD (peer, BGP_Stop);
3480
3481 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3482 }
3483
3484 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3485 {
3486 if (peer->password && strcmp (peer->password, password) == 0)
3487 continue;
3488
3489 if (peer->password)
3490 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3491
3492 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3493
3494 if (peer->status == Established)
3495 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3496 else
3497 BGP_EVENT_ADD (peer, BGP_Stop);
3498
3499 if (bgp_md5_set (peer) < 0)
3500 ret = BGP_ERR_TCPSIG_FAILED;
3501 }
3502
3503 return ret;
3504}
3505
3506int
3507peer_password_unset (struct peer *peer)
3508{
3509 struct listnode *nn, *nnode;
3510
3511 if (!peer->password
3512 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3513 return 0;
3514
3515 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3516 {
3517 if (peer_group_active (peer)
3518 && peer->group->conf->password
3519 && strcmp (peer->group->conf->password, peer->password) == 0)
3520 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3521
3522 if (peer->status == Established)
3523 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3524 else
3525 BGP_EVENT_ADD (peer, BGP_Stop);
3526
3527 if (peer->password)
3528 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3529
3530 peer->password = NULL;
3531
3532 bgp_md5_set (peer);
3533
3534 return 0;
3535 }
3536
3537 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3538 peer->password = NULL;
3539
3540 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3541 {
3542 if (!peer->password)
3543 continue;
3544
3545 if (peer->status == Established)
3546 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3547 else
3548 BGP_EVENT_ADD (peer, BGP_Stop);
3549
3550 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3551 peer->password = NULL;
3552
3553 bgp_md5_set (peer);
3554 }
3555
3556 return 0;
3557}
3558
paul718e3742002-12-13 20:15:29 +00003559/* Set distribute list to the peer. */
3560int
3561peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003562 const char *name)
paul718e3742002-12-13 20:15:29 +00003563{
3564 struct bgp_filter *filter;
3565 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003566 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003567
3568 if (! peer->afc[afi][safi])
3569 return BGP_ERR_PEER_INACTIVE;
3570
3571 if (direct != FILTER_IN && direct != FILTER_OUT)
3572 return BGP_ERR_INVALID_VALUE;
3573
3574 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3575 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3576
3577 filter = &peer->filter[afi][safi];
3578
3579 if (filter->plist[direct].name)
3580 return BGP_ERR_PEER_FILTER_CONFLICT;
3581
3582 if (filter->dlist[direct].name)
3583 free (filter->dlist[direct].name);
3584 filter->dlist[direct].name = strdup (name);
3585 filter->dlist[direct].alist = access_list_lookup (afi, name);
3586
3587 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3588 return 0;
3589
3590 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003591 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003592 {
3593 filter = &peer->filter[afi][safi];
3594
3595 if (! peer->af_group[afi][safi])
3596 continue;
3597
3598 if (filter->dlist[direct].name)
3599 free (filter->dlist[direct].name);
3600 filter->dlist[direct].name = strdup (name);
3601 filter->dlist[direct].alist = access_list_lookup (afi, name);
3602 }
3603
3604 return 0;
3605}
3606
3607int
3608peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3609{
3610 struct bgp_filter *filter;
3611 struct bgp_filter *gfilter;
3612 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003613 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003614
3615 if (! peer->afc[afi][safi])
3616 return BGP_ERR_PEER_INACTIVE;
3617
3618 if (direct != FILTER_IN && direct != FILTER_OUT)
3619 return BGP_ERR_INVALID_VALUE;
3620
3621 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3622 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3623
3624 filter = &peer->filter[afi][safi];
3625
3626 /* apply peer-group filter */
3627 if (peer->af_group[afi][safi])
3628 {
3629 gfilter = &peer->group->conf->filter[afi][safi];
3630
3631 if (gfilter->dlist[direct].name)
3632 {
3633 if (filter->dlist[direct].name)
3634 free (filter->dlist[direct].name);
3635 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3636 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3637 return 0;
3638 }
3639 }
3640
3641 if (filter->dlist[direct].name)
3642 free (filter->dlist[direct].name);
3643 filter->dlist[direct].name = NULL;
3644 filter->dlist[direct].alist = NULL;
3645
3646 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3647 return 0;
3648
3649 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003650 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003651 {
3652 filter = &peer->filter[afi][safi];
3653
3654 if (! peer->af_group[afi][safi])
3655 continue;
3656
3657 if (filter->dlist[direct].name)
3658 free (filter->dlist[direct].name);
3659 filter->dlist[direct].name = NULL;
3660 filter->dlist[direct].alist = NULL;
3661 }
3662
3663 return 0;
3664}
3665
3666/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003667static void
paul718e3742002-12-13 20:15:29 +00003668peer_distribute_update (struct access_list *access)
3669{
3670 afi_t afi;
3671 safi_t safi;
3672 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003673 struct listnode *mnode, *mnnode;
3674 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003675 struct bgp *bgp;
3676 struct peer *peer;
3677 struct peer_group *group;
3678 struct bgp_filter *filter;
3679
paul1eb8ef22005-04-07 07:30:20 +00003680 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003681 {
paul1eb8ef22005-04-07 07:30:20 +00003682 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003683 {
3684 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3685 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3686 {
3687 filter = &peer->filter[afi][safi];
3688
3689 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3690 {
3691 if (filter->dlist[direct].name)
3692 filter->dlist[direct].alist =
3693 access_list_lookup (afi, filter->dlist[direct].name);
3694 else
3695 filter->dlist[direct].alist = NULL;
3696 }
3697 }
3698 }
paul1eb8ef22005-04-07 07:30:20 +00003699 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003700 {
3701 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3702 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3703 {
3704 filter = &group->conf->filter[afi][safi];
3705
3706 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3707 {
3708 if (filter->dlist[direct].name)
3709 filter->dlist[direct].alist =
3710 access_list_lookup (afi, filter->dlist[direct].name);
3711 else
3712 filter->dlist[direct].alist = NULL;
3713 }
3714 }
3715 }
3716 }
3717}
3718
3719/* Set prefix list to the peer. */
3720int
3721peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003722 const char *name)
paul718e3742002-12-13 20:15:29 +00003723{
3724 struct bgp_filter *filter;
3725 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003727
3728 if (! peer->afc[afi][safi])
3729 return BGP_ERR_PEER_INACTIVE;
3730
3731 if (direct != FILTER_IN && direct != FILTER_OUT)
3732 return BGP_ERR_INVALID_VALUE;
3733
3734 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3735 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3736
3737 filter = &peer->filter[afi][safi];
3738
3739 if (filter->dlist[direct].name)
3740 return BGP_ERR_PEER_FILTER_CONFLICT;
3741
3742 if (filter->plist[direct].name)
3743 free (filter->plist[direct].name);
3744 filter->plist[direct].name = strdup (name);
3745 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3746
3747 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3748 return 0;
3749
3750 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003751 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003752 {
3753 filter = &peer->filter[afi][safi];
3754
3755 if (! peer->af_group[afi][safi])
3756 continue;
3757
3758 if (filter->plist[direct].name)
3759 free (filter->plist[direct].name);
3760 filter->plist[direct].name = strdup (name);
3761 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3762 }
3763 return 0;
3764}
3765
3766int
3767peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3768{
3769 struct bgp_filter *filter;
3770 struct bgp_filter *gfilter;
3771 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003772 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003773
3774 if (! peer->afc[afi][safi])
3775 return BGP_ERR_PEER_INACTIVE;
3776
3777 if (direct != FILTER_IN && direct != FILTER_OUT)
3778 return BGP_ERR_INVALID_VALUE;
3779
3780 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3781 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3782
3783 filter = &peer->filter[afi][safi];
3784
3785 /* apply peer-group filter */
3786 if (peer->af_group[afi][safi])
3787 {
3788 gfilter = &peer->group->conf->filter[afi][safi];
3789
3790 if (gfilter->plist[direct].name)
3791 {
3792 if (filter->plist[direct].name)
3793 free (filter->plist[direct].name);
3794 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3795 filter->plist[direct].plist = gfilter->plist[direct].plist;
3796 return 0;
3797 }
3798 }
3799
3800 if (filter->plist[direct].name)
3801 free (filter->plist[direct].name);
3802 filter->plist[direct].name = NULL;
3803 filter->plist[direct].plist = NULL;
3804
3805 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3806 return 0;
3807
3808 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003809 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003810 {
3811 filter = &peer->filter[afi][safi];
3812
3813 if (! peer->af_group[afi][safi])
3814 continue;
3815
3816 if (filter->plist[direct].name)
3817 free (filter->plist[direct].name);
3818 filter->plist[direct].name = NULL;
3819 filter->plist[direct].plist = NULL;
3820 }
3821
3822 return 0;
3823}
3824
3825/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003826static void
paul718e3742002-12-13 20:15:29 +00003827peer_prefix_list_update (struct prefix_list *plist)
3828{
paul1eb8ef22005-04-07 07:30:20 +00003829 struct listnode *mnode, *mnnode;
3830 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003831 struct bgp *bgp;
3832 struct peer *peer;
3833 struct peer_group *group;
3834 struct bgp_filter *filter;
3835 afi_t afi;
3836 safi_t safi;
3837 int direct;
3838
paul1eb8ef22005-04-07 07:30:20 +00003839 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003840 {
paul1eb8ef22005-04-07 07:30:20 +00003841 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003842 {
3843 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3844 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3845 {
3846 filter = &peer->filter[afi][safi];
3847
3848 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3849 {
3850 if (filter->plist[direct].name)
3851 filter->plist[direct].plist =
3852 prefix_list_lookup (afi, filter->plist[direct].name);
3853 else
3854 filter->plist[direct].plist = NULL;
3855 }
3856 }
3857 }
paul1eb8ef22005-04-07 07:30:20 +00003858 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003859 {
3860 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3861 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3862 {
3863 filter = &group->conf->filter[afi][safi];
3864
3865 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3866 {
3867 if (filter->plist[direct].name)
3868 filter->plist[direct].plist =
3869 prefix_list_lookup (afi, filter->plist[direct].name);
3870 else
3871 filter->plist[direct].plist = NULL;
3872 }
3873 }
3874 }
3875 }
3876}
3877
3878int
3879peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003880 const char *name)
paul718e3742002-12-13 20:15:29 +00003881{
3882 struct bgp_filter *filter;
3883 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003884 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003885
3886 if (! peer->afc[afi][safi])
3887 return BGP_ERR_PEER_INACTIVE;
3888
3889 if (direct != FILTER_IN && direct != FILTER_OUT)
3890 return BGP_ERR_INVALID_VALUE;
3891
3892 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3893 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3894
3895 filter = &peer->filter[afi][safi];
3896
3897 if (filter->aslist[direct].name)
3898 free (filter->aslist[direct].name);
3899 filter->aslist[direct].name = strdup (name);
3900 filter->aslist[direct].aslist = as_list_lookup (name);
3901
3902 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3903 return 0;
3904
3905 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003906 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003907 {
3908 filter = &peer->filter[afi][safi];
3909
3910 if (! peer->af_group[afi][safi])
3911 continue;
3912
3913 if (filter->aslist[direct].name)
3914 free (filter->aslist[direct].name);
3915 filter->aslist[direct].name = strdup (name);
3916 filter->aslist[direct].aslist = as_list_lookup (name);
3917 }
3918 return 0;
3919}
3920
3921int
3922peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3923{
3924 struct bgp_filter *filter;
3925 struct bgp_filter *gfilter;
3926 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003927 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003928
3929 if (! peer->afc[afi][safi])
3930 return BGP_ERR_PEER_INACTIVE;
3931
hassob5f29602005-05-25 21:00:28 +00003932 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003933 return BGP_ERR_INVALID_VALUE;
3934
hassob5f29602005-05-25 21:00:28 +00003935 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003936 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3937
3938 filter = &peer->filter[afi][safi];
3939
3940 /* apply peer-group filter */
3941 if (peer->af_group[afi][safi])
3942 {
3943 gfilter = &peer->group->conf->filter[afi][safi];
3944
3945 if (gfilter->aslist[direct].name)
3946 {
3947 if (filter->aslist[direct].name)
3948 free (filter->aslist[direct].name);
3949 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3950 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3951 return 0;
3952 }
3953 }
3954
3955 if (filter->aslist[direct].name)
3956 free (filter->aslist[direct].name);
3957 filter->aslist[direct].name = NULL;
3958 filter->aslist[direct].aslist = NULL;
3959
3960 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3961 return 0;
3962
3963 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003964 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003965 {
3966 filter = &peer->filter[afi][safi];
3967
3968 if (! peer->af_group[afi][safi])
3969 continue;
3970
3971 if (filter->aslist[direct].name)
3972 free (filter->aslist[direct].name);
3973 filter->aslist[direct].name = NULL;
3974 filter->aslist[direct].aslist = NULL;
3975 }
3976
3977 return 0;
3978}
3979
paul94f2b392005-06-28 12:44:16 +00003980static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003981peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003982{
3983 afi_t afi;
3984 safi_t safi;
3985 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003986 struct listnode *mnode, *mnnode;
3987 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003988 struct bgp *bgp;
3989 struct peer *peer;
3990 struct peer_group *group;
3991 struct bgp_filter *filter;
3992
paul1eb8ef22005-04-07 07:30:20 +00003993 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003994 {
paul1eb8ef22005-04-07 07:30:20 +00003995 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003996 {
3997 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3998 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3999 {
4000 filter = &peer->filter[afi][safi];
4001
4002 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4003 {
4004 if (filter->aslist[direct].name)
4005 filter->aslist[direct].aslist =
4006 as_list_lookup (filter->aslist[direct].name);
4007 else
4008 filter->aslist[direct].aslist = NULL;
4009 }
4010 }
4011 }
paul1eb8ef22005-04-07 07:30:20 +00004012 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004013 {
4014 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4015 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4016 {
4017 filter = &group->conf->filter[afi][safi];
4018
4019 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4020 {
4021 if (filter->aslist[direct].name)
4022 filter->aslist[direct].aslist =
4023 as_list_lookup (filter->aslist[direct].name);
4024 else
4025 filter->aslist[direct].aslist = NULL;
4026 }
4027 }
4028 }
4029 }
4030}
4031
4032/* Set route-map to the peer. */
4033int
4034peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004035 const char *name)
paul718e3742002-12-13 20:15:29 +00004036{
4037 struct bgp_filter *filter;
4038 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004039 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004040
4041 if (! peer->afc[afi][safi])
4042 return BGP_ERR_PEER_INACTIVE;
4043
paulfee0f4c2004-09-13 05:12:46 +00004044 if (direct != RMAP_IN && direct != RMAP_OUT &&
4045 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004046 return BGP_ERR_INVALID_VALUE;
4047
paulfee0f4c2004-09-13 05:12:46 +00004048 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4049 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004050 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4051
4052 filter = &peer->filter[afi][safi];
4053
4054 if (filter->map[direct].name)
4055 free (filter->map[direct].name);
4056
4057 filter->map[direct].name = strdup (name);
4058 filter->map[direct].map = route_map_lookup_by_name (name);
4059
4060 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4061 return 0;
4062
4063 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004064 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004065 {
4066 filter = &peer->filter[afi][safi];
4067
4068 if (! peer->af_group[afi][safi])
4069 continue;
4070
4071 if (filter->map[direct].name)
4072 free (filter->map[direct].name);
4073 filter->map[direct].name = strdup (name);
4074 filter->map[direct].map = route_map_lookup_by_name (name);
4075 }
4076 return 0;
4077}
4078
4079/* Unset route-map from the peer. */
4080int
4081peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4082{
4083 struct bgp_filter *filter;
4084 struct bgp_filter *gfilter;
4085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004086 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004087
4088 if (! peer->afc[afi][safi])
4089 return BGP_ERR_PEER_INACTIVE;
4090
hassob5f29602005-05-25 21:00:28 +00004091 if (direct != RMAP_IN && direct != RMAP_OUT &&
4092 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004093 return BGP_ERR_INVALID_VALUE;
4094
hassob5f29602005-05-25 21:00:28 +00004095 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4096 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004097 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4098
4099 filter = &peer->filter[afi][safi];
4100
4101 /* apply peer-group filter */
4102 if (peer->af_group[afi][safi])
4103 {
4104 gfilter = &peer->group->conf->filter[afi][safi];
4105
4106 if (gfilter->map[direct].name)
4107 {
4108 if (filter->map[direct].name)
4109 free (filter->map[direct].name);
4110 filter->map[direct].name = strdup (gfilter->map[direct].name);
4111 filter->map[direct].map = gfilter->map[direct].map;
4112 return 0;
4113 }
4114 }
4115
4116 if (filter->map[direct].name)
4117 free (filter->map[direct].name);
4118 filter->map[direct].name = NULL;
4119 filter->map[direct].map = NULL;
4120
4121 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4122 return 0;
4123
4124 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004125 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004126 {
4127 filter = &peer->filter[afi][safi];
4128
4129 if (! peer->af_group[afi][safi])
4130 continue;
4131
4132 if (filter->map[direct].name)
4133 free (filter->map[direct].name);
4134 filter->map[direct].name = NULL;
4135 filter->map[direct].map = NULL;
4136 }
4137 return 0;
4138}
4139
4140/* Set unsuppress-map to the peer. */
4141int
paulfd79ac92004-10-13 05:06:08 +00004142peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4143 const char *name)
paul718e3742002-12-13 20:15:29 +00004144{
4145 struct bgp_filter *filter;
4146 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004147 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004148
4149 if (! peer->afc[afi][safi])
4150 return BGP_ERR_PEER_INACTIVE;
4151
4152 if (peer_is_group_member (peer, afi, safi))
4153 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4154
4155 filter = &peer->filter[afi][safi];
4156
4157 if (filter->usmap.name)
4158 free (filter->usmap.name);
4159
4160 filter->usmap.name = strdup (name);
4161 filter->usmap.map = route_map_lookup_by_name (name);
4162
4163 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4164 return 0;
4165
4166 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004167 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004168 {
4169 filter = &peer->filter[afi][safi];
4170
4171 if (! peer->af_group[afi][safi])
4172 continue;
4173
4174 if (filter->usmap.name)
4175 free (filter->usmap.name);
4176 filter->usmap.name = strdup (name);
4177 filter->usmap.map = route_map_lookup_by_name (name);
4178 }
4179 return 0;
4180}
4181
4182/* Unset route-map from the peer. */
4183int
4184peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4185{
4186 struct bgp_filter *filter;
4187 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004188 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004189
4190 if (! peer->afc[afi][safi])
4191 return BGP_ERR_PEER_INACTIVE;
4192
4193 if (peer_is_group_member (peer, afi, safi))
4194 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4195
4196 filter = &peer->filter[afi][safi];
4197
4198 if (filter->usmap.name)
4199 free (filter->usmap.name);
4200 filter->usmap.name = NULL;
4201 filter->usmap.map = NULL;
4202
4203 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4204 return 0;
4205
4206 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004207 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004208 {
4209 filter = &peer->filter[afi][safi];
4210
4211 if (! peer->af_group[afi][safi])
4212 continue;
4213
4214 if (filter->usmap.name)
4215 free (filter->usmap.name);
4216 filter->usmap.name = NULL;
4217 filter->usmap.map = NULL;
4218 }
4219 return 0;
4220}
4221
4222int
4223peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004224 u_int32_t max, u_char threshold,
4225 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004226{
4227 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004228 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004229
4230 if (! peer->afc[afi][safi])
4231 return BGP_ERR_PEER_INACTIVE;
4232
4233 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4234 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004235 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004236 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004237 if (warning)
4238 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4239 else
4240 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4241
4242 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4243 return 0;
4244
4245 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004246 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004247 {
4248 if (! peer->af_group[afi][safi])
4249 continue;
4250
4251 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4252 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004253 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004254 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004255 if (warning)
4256 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4257 else
4258 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4259 }
4260 return 0;
4261}
4262
4263int
4264peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4265{
4266 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004268
4269 if (! peer->afc[afi][safi])
4270 return BGP_ERR_PEER_INACTIVE;
4271
4272 /* apply peer-group config */
4273 if (peer->af_group[afi][safi])
4274 {
4275 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4276 PEER_FLAG_MAX_PREFIX))
4277 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4278 else
4279 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4280
4281 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4282 PEER_FLAG_MAX_PREFIX_WARNING))
4283 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4284 else
4285 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4286
4287 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004288 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004289 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004290 return 0;
4291 }
4292
4293 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4294 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4295 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004296 peer->pmax_threshold[afi][safi] = 0;
4297 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004298
4299 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4300 return 0;
4301
4302 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004303 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004304 {
4305 if (! peer->af_group[afi][safi])
4306 continue;
4307
4308 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4309 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4310 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004311 peer->pmax_threshold[afi][safi] = 0;
4312 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004313 }
4314 return 0;
4315}
4316
4317int
4318peer_clear (struct peer *peer)
4319{
4320 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4321 {
hasso0a486e52005-02-01 20:57:17 +00004322 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4323 {
4324 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4325 if (peer->t_pmax_restart)
4326 {
4327 BGP_TIMER_OFF (peer->t_pmax_restart);
4328 if (BGP_DEBUG (events, EVENTS))
4329 zlog_debug ("%s Maximum-prefix restart timer canceled",
4330 peer->host);
4331 }
4332 BGP_EVENT_ADD (peer, BGP_Start);
4333 return 0;
4334 }
4335
paul718e3742002-12-13 20:15:29 +00004336 peer->v_start = BGP_INIT_START_TIMER;
4337 if (peer->status == Established)
4338 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4339 BGP_NOTIFY_CEASE_ADMIN_RESET);
4340 else
4341 BGP_EVENT_ADD (peer, BGP_Stop);
4342 }
4343 return 0;
4344}
4345
4346int
4347peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4348 enum bgp_clear_type stype)
4349{
4350 if (peer->status != Established)
4351 return 0;
4352
4353 if (! peer->afc[afi][safi])
4354 return BGP_ERR_AF_UNCONFIGURED;
4355
paulfee0f4c2004-09-13 05:12:46 +00004356 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4357 {
4358 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4359 return 0;
4360 bgp_check_local_routes_rsclient (peer, afi, safi);
4361 bgp_soft_reconfig_rsclient (peer, afi, safi);
4362 }
4363
paul718e3742002-12-13 20:15:29 +00004364 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4365 bgp_announce_route (peer, afi, safi);
4366
4367 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4368 {
4369 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4370 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4371 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4372 {
4373 struct bgp_filter *filter = &peer->filter[afi][safi];
4374 u_char prefix_type;
4375
4376 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4377 prefix_type = ORF_TYPE_PREFIX;
4378 else
4379 prefix_type = ORF_TYPE_PREFIX_OLD;
4380
4381 if (filter->plist[FILTER_IN].plist)
4382 {
4383 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4384 bgp_route_refresh_send (peer, afi, safi,
4385 prefix_type, REFRESH_DEFER, 1);
4386 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4387 REFRESH_IMMEDIATE, 0);
4388 }
4389 else
4390 {
4391 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4392 bgp_route_refresh_send (peer, afi, safi,
4393 prefix_type, REFRESH_IMMEDIATE, 1);
4394 else
4395 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4396 }
4397 return 0;
4398 }
4399 }
4400
4401 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4402 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4403 {
4404 /* If neighbor has soft reconfiguration inbound flag.
4405 Use Adj-RIB-In database. */
4406 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4407 bgp_soft_reconfig_in (peer, afi, safi);
4408 else
4409 {
4410 /* If neighbor has route refresh capability, send route refresh
4411 message to the peer. */
4412 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4413 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4414 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4415 else
4416 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4417 }
4418 }
4419 return 0;
4420}
4421
paulfd79ac92004-10-13 05:06:08 +00004422/* Display peer uptime.*/
4423/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004424char *
4425peer_uptime (time_t uptime2, char *buf, size_t len)
4426{
4427 time_t uptime1;
4428 struct tm *tm;
4429
4430 /* Check buffer length. */
4431 if (len < BGP_UPTIME_LEN)
4432 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004433 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004434 /* XXX: should return status instead of buf... */
4435 snprintf (buf, len, "<error> ");
4436 return buf;
paul718e3742002-12-13 20:15:29 +00004437 }
4438
4439 /* If there is no connection has been done before print `never'. */
4440 if (uptime2 == 0)
4441 {
4442 snprintf (buf, len, "never ");
4443 return buf;
4444 }
4445
4446 /* Get current time. */
4447 uptime1 = time (NULL);
4448 uptime1 -= uptime2;
4449 tm = gmtime (&uptime1);
4450
4451 /* Making formatted timer strings. */
4452#define ONE_DAY_SECOND 60*60*24
4453#define ONE_WEEK_SECOND 60*60*24*7
4454
4455 if (uptime1 < ONE_DAY_SECOND)
4456 snprintf (buf, len, "%02d:%02d:%02d",
4457 tm->tm_hour, tm->tm_min, tm->tm_sec);
4458 else if (uptime1 < ONE_WEEK_SECOND)
4459 snprintf (buf, len, "%dd%02dh%02dm",
4460 tm->tm_yday, tm->tm_hour, tm->tm_min);
4461 else
4462 snprintf (buf, len, "%02dw%dd%02dh",
4463 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4464 return buf;
4465}
4466
paul94f2b392005-06-28 12:44:16 +00004467static void
paul718e3742002-12-13 20:15:29 +00004468bgp_config_write_filter (struct vty *vty, struct peer *peer,
4469 afi_t afi, safi_t safi)
4470{
4471 struct bgp_filter *filter;
4472 struct bgp_filter *gfilter = NULL;
4473 char *addr;
4474 int in = FILTER_IN;
4475 int out = FILTER_OUT;
4476
4477 addr = peer->host;
4478 filter = &peer->filter[afi][safi];
4479 if (peer->af_group[afi][safi])
4480 gfilter = &peer->group->conf->filter[afi][safi];
4481
4482 /* distribute-list. */
4483 if (filter->dlist[in].name)
4484 if (! gfilter || ! gfilter->dlist[in].name
4485 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4486 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4487 filter->dlist[in].name, VTY_NEWLINE);
4488 if (filter->dlist[out].name && ! gfilter)
4489 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4490 filter->dlist[out].name, VTY_NEWLINE);
4491
4492 /* prefix-list. */
4493 if (filter->plist[in].name)
4494 if (! gfilter || ! gfilter->plist[in].name
4495 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4496 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4497 filter->plist[in].name, VTY_NEWLINE);
4498 if (filter->plist[out].name && ! gfilter)
4499 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4500 filter->plist[out].name, VTY_NEWLINE);
4501
4502 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004503 if (filter->map[RMAP_IN].name)
4504 if (! gfilter || ! gfilter->map[RMAP_IN].name
4505 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004506 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004507 filter->map[RMAP_IN].name, VTY_NEWLINE);
4508 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004509 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004510 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4511 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4512 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4513 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4514 if (filter->map[RMAP_EXPORT].name)
4515 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4516 || strcmp (filter->map[RMAP_EXPORT].name,
4517 gfilter->map[RMAP_EXPORT].name) != 0)
4518 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4519 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004520
4521 /* unsuppress-map */
4522 if (filter->usmap.name && ! gfilter)
4523 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4524 filter->usmap.name, VTY_NEWLINE);
4525
4526 /* filter-list. */
4527 if (filter->aslist[in].name)
4528 if (! gfilter || ! gfilter->aslist[in].name
4529 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4530 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4531 filter->aslist[in].name, VTY_NEWLINE);
4532 if (filter->aslist[out].name && ! gfilter)
4533 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4534 filter->aslist[out].name, VTY_NEWLINE);
4535}
4536
4537/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004538static void
paul718e3742002-12-13 20:15:29 +00004539bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4540 struct peer *peer, afi_t afi, safi_t safi)
4541{
4542 struct bgp_filter *filter;
4543 struct peer *g_peer = NULL;
4544 char buf[SU_ADDRSTRLEN];
4545 char *addr;
4546
4547 filter = &peer->filter[afi][safi];
4548 addr = peer->host;
4549 if (peer_group_active (peer))
4550 g_peer = peer->group->conf;
4551
4552 /************************************
4553 ****** Global to the neighbor ******
4554 ************************************/
4555 if (afi == AFI_IP && safi == SAFI_UNICAST)
4556 {
4557 /* remote-as. */
4558 if (! peer_group_active (peer))
4559 {
4560 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4561 vty_out (vty, " neighbor %s peer-group%s", addr,
4562 VTY_NEWLINE);
4563 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004564 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004565 VTY_NEWLINE);
4566 }
4567 else
4568 {
4569 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004570 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004571 VTY_NEWLINE);
4572 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4573 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4574 peer->group->name, VTY_NEWLINE);
4575 }
4576
4577 /* local-as. */
4578 if (peer->change_local_as)
4579 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004580 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004581 peer->change_local_as,
4582 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4583 " no-prepend" : "", VTY_NEWLINE);
4584
4585 /* Description. */
4586 if (peer->desc)
4587 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4588 VTY_NEWLINE);
4589
4590 /* Shutdown. */
4591 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4592 if (! peer_group_active (peer) ||
4593 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4594 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4595
Paul Jakma0df7c912008-07-21 21:02:49 +00004596 /* Password. */
4597 if (peer->password)
4598 if (!peer_group_active (peer)
4599 || ! g_peer->password
4600 || strcmp (peer->password, g_peer->password) != 0)
4601 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4602 VTY_NEWLINE);
4603
paul718e3742002-12-13 20:15:29 +00004604 /* BGP port. */
4605 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004606 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004607 VTY_NEWLINE);
4608
4609 /* Local interface name. */
4610 if (peer->ifname)
4611 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4612 VTY_NEWLINE);
4613
4614 /* Passive. */
4615 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4616 if (! peer_group_active (peer) ||
4617 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4618 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4619
4620 /* EBGP multihop. */
4621 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4622 if (! peer_group_active (peer) ||
4623 g_peer->ttl != peer->ttl)
4624 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4625 VTY_NEWLINE);
4626
hasso6ffd2072005-02-02 14:50:11 +00004627 /* disable-connected-check. */
4628 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004629 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004630 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4631 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004632
4633 /* Update-source. */
4634 if (peer->update_if)
4635 if (! peer_group_active (peer) || ! g_peer->update_if
4636 || strcmp (g_peer->update_if, peer->update_if) != 0)
4637 vty_out (vty, " neighbor %s update-source %s%s", addr,
4638 peer->update_if, VTY_NEWLINE);
4639 if (peer->update_source)
4640 if (! peer_group_active (peer) || ! g_peer->update_source
4641 || sockunion_cmp (g_peer->update_source,
4642 peer->update_source) != 0)
4643 vty_out (vty, " neighbor %s update-source %s%s", addr,
4644 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4645 VTY_NEWLINE);
4646
paul718e3742002-12-13 20:15:29 +00004647 /* advertisement-interval */
4648 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4649 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4650 addr, peer->v_routeadv, VTY_NEWLINE);
4651
4652 /* timers. */
4653 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4654 && ! peer_group_active (peer))
4655 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4656 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4657
4658 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4659 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4660 peer->connect, VTY_NEWLINE);
4661
4662 /* Default weight. */
4663 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4664 if (! peer_group_active (peer) ||
4665 g_peer->weight != peer->weight)
4666 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4667 VTY_NEWLINE);
4668
paul718e3742002-12-13 20:15:29 +00004669 /* Dynamic capability. */
4670 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4671 if (! peer_group_active (peer) ||
4672 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4673 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4674 VTY_NEWLINE);
4675
4676 /* dont capability negotiation. */
4677 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4678 if (! peer_group_active (peer) ||
4679 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4680 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4681 VTY_NEWLINE);
4682
4683 /* override capability negotiation. */
4684 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4685 if (! peer_group_active (peer) ||
4686 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4687 vty_out (vty, " neighbor %s override-capability%s", addr,
4688 VTY_NEWLINE);
4689
4690 /* strict capability negotiation. */
4691 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4692 if (! peer_group_active (peer) ||
4693 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4694 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4695 VTY_NEWLINE);
4696
4697 if (! peer_group_active (peer))
4698 {
4699 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4700 {
4701 if (peer->afc[AFI_IP][SAFI_UNICAST])
4702 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4703 }
4704 else
4705 {
4706 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4707 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4708 }
4709 }
4710 }
4711
4712
4713 /************************************
4714 ****** Per AF to the neighbor ******
4715 ************************************/
4716
4717 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4718 {
4719 if (peer->af_group[afi][safi])
4720 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4721 peer->group->name, VTY_NEWLINE);
4722 else
4723 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4724 }
4725
4726 /* ORF capability. */
4727 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4728 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4729 if (! peer->af_group[afi][safi])
4730 {
4731 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4732
4733 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4734 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4735 vty_out (vty, " both");
4736 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4737 vty_out (vty, " send");
4738 else
4739 vty_out (vty, " receive");
4740 vty_out (vty, "%s", VTY_NEWLINE);
4741 }
4742
4743 /* Route reflector client. */
4744 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4745 && ! peer->af_group[afi][safi])
4746 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4747 VTY_NEWLINE);
4748
4749 /* Nexthop self. */
4750 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4751 && ! peer->af_group[afi][safi])
4752 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4753
4754 /* Remove private AS. */
4755 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4756 && ! peer->af_group[afi][safi])
4757 vty_out (vty, " neighbor %s remove-private-AS%s",
4758 addr, VTY_NEWLINE);
4759
4760 /* send-community print. */
4761 if (! peer->af_group[afi][safi])
4762 {
4763 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4764 {
4765 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4766 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4767 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4768 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4769 vty_out (vty, " neighbor %s send-community extended%s",
4770 addr, VTY_NEWLINE);
4771 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4772 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4773 }
4774 else
4775 {
4776 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4777 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4778 vty_out (vty, " no neighbor %s send-community both%s",
4779 addr, VTY_NEWLINE);
4780 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4781 vty_out (vty, " no neighbor %s send-community extended%s",
4782 addr, VTY_NEWLINE);
4783 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4784 vty_out (vty, " no neighbor %s send-community%s",
4785 addr, VTY_NEWLINE);
4786 }
4787 }
4788
4789 /* Default information */
4790 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4791 && ! peer->af_group[afi][safi])
4792 {
4793 vty_out (vty, " neighbor %s default-originate", addr);
4794 if (peer->default_rmap[afi][safi].name)
4795 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4796 vty_out (vty, "%s", VTY_NEWLINE);
4797 }
4798
4799 /* Soft reconfiguration inbound. */
4800 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4801 if (! peer->af_group[afi][safi] ||
4802 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4803 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4804 VTY_NEWLINE);
4805
4806 /* maximum-prefix. */
4807 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4808 if (! peer->af_group[afi][safi]
4809 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004810 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004811 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4812 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004813 {
hasso0a486e52005-02-01 20:57:17 +00004814 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4815 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4816 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4817 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4818 vty_out (vty, " warning-only");
4819 if (peer->pmax_restart[afi][safi])
4820 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4821 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004822 }
paul718e3742002-12-13 20:15:29 +00004823
4824 /* Route server client. */
4825 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4826 && ! peer->af_group[afi][safi])
4827 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4828
4829 /* Allow AS in. */
4830 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4831 if (! peer_group_active (peer)
4832 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4833 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4834 {
4835 if (peer->allowas_in[afi][safi] == 3)
4836 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4837 else
4838 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4839 peer->allowas_in[afi][safi], VTY_NEWLINE);
4840 }
4841
4842 /* Filter. */
4843 bgp_config_write_filter (vty, peer, afi, safi);
4844
4845 /* atribute-unchanged. */
4846 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4847 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4848 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4849 && ! peer->af_group[afi][safi])
4850 {
4851 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4852 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4853 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4854 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4855 else
4856 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4857 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4858 " as-path" : "",
4859 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4860 " next-hop" : "",
4861 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4862 " med" : "", VTY_NEWLINE);
4863 }
4864}
4865
4866/* Display "address-family" configuration header. */
4867void
4868bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4869 int *write)
4870{
4871 if (*write)
4872 return;
4873
4874 if (afi == AFI_IP && safi == SAFI_UNICAST)
4875 return;
4876
4877 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4878
4879 if (afi == AFI_IP)
4880 {
4881 if (safi == SAFI_MULTICAST)
4882 vty_out (vty, "ipv4 multicast");
4883 else if (safi == SAFI_MPLS_VPN)
4884 vty_out (vty, "vpnv4 unicast");
4885 }
4886 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004887 {
4888 vty_out (vty, "ipv6");
4889
4890 if (safi == SAFI_MULTICAST)
4891 vty_out (vty, " multicast");
4892 }
paul718e3742002-12-13 20:15:29 +00004893
4894 vty_out (vty, "%s", VTY_NEWLINE);
4895
4896 *write = 1;
4897}
4898
4899/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004900static int
paul718e3742002-12-13 20:15:29 +00004901bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4902 safi_t safi)
4903{
4904 int write = 0;
4905 struct peer *peer;
4906 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004907 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004908
4909 bgp_config_write_network (vty, bgp, afi, safi, &write);
4910
4911 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4912
paul1eb8ef22005-04-07 07:30:20 +00004913 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004914 {
4915 if (group->conf->afc[afi][safi])
4916 {
4917 bgp_config_write_family_header (vty, afi, safi, &write);
4918 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4919 }
4920 }
paul1eb8ef22005-04-07 07:30:20 +00004921 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004922 {
4923 if (peer->afc[afi][safi])
4924 {
4925 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4926 {
4927 bgp_config_write_family_header (vty, afi, safi, &write);
4928 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4929 }
4930 }
4931 }
4932 if (write)
4933 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4934
4935 return write;
4936}
4937
4938int
4939bgp_config_write (struct vty *vty)
4940{
4941 int write = 0;
4942 struct bgp *bgp;
4943 struct peer_group *group;
4944 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004945 struct listnode *node, *nnode;
4946 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004947
4948 /* BGP Multiple instance. */
4949 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4950 {
4951 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4952 write++;
4953 }
4954
4955 /* BGP Config type. */
4956 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4957 {
4958 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4959 write++;
4960 }
4961
4962 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004963 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004964 {
4965 if (write)
4966 vty_out (vty, "!%s", VTY_NEWLINE);
4967
4968 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004969 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004970
4971 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4972 {
4973 if (bgp->name)
4974 vty_out (vty, " view %s", bgp->name);
4975 }
4976 vty_out (vty, "%s", VTY_NEWLINE);
4977
4978 /* No Synchronization */
4979 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4980 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4981
4982 /* BGP fast-external-failover. */
4983 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4984 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4985
4986 /* BGP router ID. */
4987 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4988 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4989 VTY_NEWLINE);
4990
paul848973c2003-08-13 00:32:49 +00004991 /* BGP log-neighbor-changes. */
4992 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4993 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4994
paul718e3742002-12-13 20:15:29 +00004995 /* BGP configuration. */
4996 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4997 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4998
4999 /* BGP default ipv4-unicast. */
5000 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5001 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5002
5003 /* BGP default local-preference. */
5004 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5005 vty_out (vty, " bgp default local-preference %d%s",
5006 bgp->default_local_pref, VTY_NEWLINE);
5007
5008 /* BGP client-to-client reflection. */
5009 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5010 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5011
5012 /* BGP cluster ID. */
5013 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5014 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5015 VTY_NEWLINE);
5016
hassoe0701b72004-05-20 09:19:34 +00005017 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005018 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005019 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5020 VTY_NEWLINE);
5021
5022 /* Confederation peer */
5023 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005024 {
hassoe0701b72004-05-20 09:19:34 +00005025 int i;
paul718e3742002-12-13 20:15:29 +00005026
hassoe0701b72004-05-20 09:19:34 +00005027 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005028
hassoe0701b72004-05-20 09:19:34 +00005029 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005030 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005031
hassoe0701b72004-05-20 09:19:34 +00005032 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005033 }
5034
5035 /* BGP enforce-first-as. */
5036 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5037 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5038
5039 /* BGP deterministic-med. */
5040 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5041 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005042
5043 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005044 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5045 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5046 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005047 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5048 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5049
paul718e3742002-12-13 20:15:29 +00005050 /* BGP bestpath method. */
5051 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5052 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005053 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5054 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005055 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5056 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5057 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5058 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5059 {
5060 vty_out (vty, " bgp bestpath med");
5061 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5062 vty_out (vty, " confed");
5063 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5064 vty_out (vty, " missing-as-worst");
5065 vty_out (vty, "%s", VTY_NEWLINE);
5066 }
5067
5068 /* BGP network import check. */
5069 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5070 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5071
5072 /* BGP scan interval. */
5073 bgp_config_write_scan_time (vty);
5074
5075 /* BGP flag dampening. */
5076 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5077 BGP_CONFIG_DAMPENING))
5078 bgp_config_write_damp (vty);
5079
5080 /* BGP static route configuration. */
5081 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5082
5083 /* BGP redistribute configuration. */
5084 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5085
5086 /* BGP timers configuration. */
5087 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5088 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5089 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5090 bgp->default_holdtime, VTY_NEWLINE);
5091
5092 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005093 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005094 {
5095 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5096 }
5097
5098 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005099 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005100 {
5101 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5102 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5103 }
5104
5105 /* Distance configuration. */
5106 bgp_config_write_distance (vty, bgp);
5107
5108 /* No auto-summary */
5109 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5110 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5111
5112 /* IPv4 multicast configuration. */
5113 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5114
5115 /* IPv4 VPN configuration. */
5116 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5117
5118 /* IPv6 unicast configuration. */
5119 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5120
Paul Jakma37a217a2007-04-10 19:20:29 +00005121 /* IPv6 multicast configuration. */
5122 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5123
paul718e3742002-12-13 20:15:29 +00005124 write++;
5125 }
5126 return write;
5127}
5128
5129void
paul94f2b392005-06-28 12:44:16 +00005130bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005131{
5132 memset (&bgp_master, 0, sizeof (struct bgp_master));
5133
5134 bm = &bgp_master;
5135 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005136 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005137 bm->port = BGP_PORT_DEFAULT;
5138 bm->master = thread_master_create ();
5139 bm->start_time = time (NULL);
5140}
paul200df112005-06-01 11:17:05 +00005141
paul718e3742002-12-13 20:15:29 +00005142
5143void
paul94f2b392005-06-28 12:44:16 +00005144bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005145{
paul718e3742002-12-13 20:15:29 +00005146 /* BGP VTY commands installation. */
5147 bgp_vty_init ();
5148
paul718e3742002-12-13 20:15:29 +00005149 /* Init zebra. */
5150 bgp_zebra_init ();
5151
5152 /* BGP inits. */
5153 bgp_attr_init ();
5154 bgp_debug_init ();
5155 bgp_dump_init ();
5156 bgp_route_init ();
5157 bgp_route_map_init ();
5158 bgp_scan_init ();
5159 bgp_mplsvpn_init ();
5160
5161 /* Access list initialize. */
5162 access_list_init ();
5163 access_list_add_hook (peer_distribute_update);
5164 access_list_delete_hook (peer_distribute_update);
5165
5166 /* Filter list initialize. */
5167 bgp_filter_init ();
5168 as_list_add_hook (peer_aslist_update);
5169 as_list_delete_hook (peer_aslist_update);
5170
5171 /* Prefix list initialize.*/
5172 prefix_list_init ();
5173 prefix_list_add_hook (peer_prefix_list_update);
5174 prefix_list_delete_hook (peer_prefix_list_update);
5175
5176 /* Community list initialize. */
5177 bgp_clist = community_list_init ();
5178
5179#ifdef HAVE_SNMP
5180 bgp_snmp_init ();
5181#endif /* HAVE_SNMP */
5182}
paul545acaf2004-04-20 15:13:15 +00005183
5184void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005185bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005186{
paul545acaf2004-04-20 15:13:15 +00005187 struct bgp *bgp;
5188 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005189 struct listnode *node, *nnode;
5190 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005191
paul1eb8ef22005-04-07 07:30:20 +00005192 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5193 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005194 if (peer->status == Established)
5195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5196 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005197
paul545acaf2004-04-20 15:13:15 +00005198 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005199
paule210cf92005-06-15 19:15:35 +00005200 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005201 {
5202 work_queue_free (bm->process_main_queue);
5203 bm->process_main_queue = NULL;
5204 }
paule210cf92005-06-15 19:15:35 +00005205 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005206 {
5207 work_queue_free (bm->process_rsclient_queue);
5208 bm->process_rsclient_queue = NULL;
5209 }
paul545acaf2004-04-20 15:13:15 +00005210}