blob: 3adede820e28778faf931c534094d6bb6ec93099 [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);
691
692 /* this /ought/ to have been done already through bgp_stop earlier,
693 * but just to be sure..
694 */
695 bgp_timer_set (peer);
696 BGP_READ_OFF (peer->t_read);
697 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000698 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000699
paul200df112005-06-01 11:17:05 +0000700 if (peer->desc)
701 XFREE (MTYPE_PEER_DESC, peer->desc);
702
703 /* Free allocated host character. */
704 if (peer->host)
705 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
706
707 /* Update source configuration. */
708 if (peer->update_source)
709 sockunion_free (peer->update_source);
710
711 if (peer->update_if)
712 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000713
714 if (peer->clear_node_queue)
715 work_queue_free (peer->clear_node_queue);
716
Paul Jakmaca058a32006-09-14 02:58:49 +0000717 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000718 memset (peer, 0, sizeof (struct peer));
719
720 XFREE (MTYPE_BGP_PEER, peer);
721}
722
723/* increase reference count on a struct peer */
724struct peer *
725peer_lock (struct peer *peer)
726{
727 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000728 assert (peer->status != Deleted);
729
paul200df112005-06-01 11:17:05 +0000730 peer->lock++;
731
732 return peer;
733}
734
735/* decrease reference count on a struct peer
736 * struct peer is freed and NULL returned if last reference
737 */
738struct peer *
739peer_unlock (struct peer *peer)
740{
741 assert (peer && (peer->lock > 0));
742
743 peer->lock--;
744
745 if (peer->lock == 0)
746 {
747#if 0
748 zlog_debug ("unlocked and freeing");
749 zlog_backtrace (LOG_DEBUG);
750#endif
751 peer_free (peer);
752 return NULL;
753 }
754
755#if 0
756 if (peer->lock == 1)
757 {
758 zlog_debug ("unlocked to 1");
759 zlog_backtrace (LOG_DEBUG);
760 }
761#endif
762
763 return peer;
764}
765
766/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000767static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000768peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000769{
770 afi_t afi;
771 safi_t safi;
772 struct peer *peer;
773 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000774
775 /* bgp argument is absolutely required */
776 assert (bgp);
777 if (!bgp)
778 return NULL;
779
paul718e3742002-12-13 20:15:29 +0000780 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000781 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000782
783 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000784 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000785 peer->v_start = BGP_INIT_START_TIMER;
786 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
787 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
788 peer->status = Idle;
789 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000790 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000791 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000792 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000793 peer = peer_lock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000794
795 /* Set default flags. */
796 for (afi = AFI_IP; afi < AFI_MAX; afi++)
797 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
798 {
799 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
800 {
801 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
802 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
803 }
804 peer->orf_plist[afi][safi] = NULL;
805 }
806 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
807
808 /* Create buffers. */
809 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
810 peer->obuf = stream_fifo_new ();
811 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
812
813 bgp_sync_init (peer);
814
815 /* Get service port number. */
816 sp = getservbyname ("bgp", "tcp");
817 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
818
819 return peer;
820}
821
822/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000823static struct peer *
paul718e3742002-12-13 20:15:29 +0000824peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
825 as_t remote_as, afi_t afi, safi_t safi)
826{
827 int active;
828 struct peer *peer;
829 char buf[SU_ADDRSTRLEN];
830
Paul Jakma6f585442006-10-22 19:13:07 +0000831 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000832 peer->su = *su;
833 peer->local_as = local_as;
834 peer->as = remote_as;
835 peer->local_id = bgp->router_id;
836 peer->v_holdtime = bgp->default_holdtime;
837 peer->v_keepalive = bgp->default_keepalive;
838 if (peer_sort (peer) == BGP_PEER_IBGP)
839 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
840 else
841 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000842
843 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000844 listnode_add_sort (bgp->peer, peer);
845
846 active = peer_active (peer);
847
848 if (afi && safi)
849 peer->afc[afi][safi] = 1;
850
851 /* Last read time set */
852 peer->readtime = time (NULL);
853
paul848973c2003-08-13 00:32:49 +0000854 /* Last reset time set */
855 peer->resettime = time (NULL);
856
paul718e3742002-12-13 20:15:29 +0000857 /* Default TTL set. */
858 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
859
860 /* Make peer's address string. */
861 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000862 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000863
864 /* Set up peer's events and timers. */
865 if (! active && peer_active (peer))
866 bgp_timer_set (peer);
867
868 return peer;
869}
870
pauleb821182004-05-01 08:44:08 +0000871/* Make accept BGP peer. Called from bgp_accept (). */
872struct peer *
873peer_create_accept (struct bgp *bgp)
874{
875 struct peer *peer;
876
Paul Jakma6f585442006-10-22 19:13:07 +0000877 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000878
879 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000880 listnode_add_sort (bgp->peer, peer);
881
882 return peer;
883}
884
paul718e3742002-12-13 20:15:29 +0000885/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000886static void
paul718e3742002-12-13 20:15:29 +0000887peer_as_change (struct peer *peer, as_t as)
888{
889 int type;
890
891 /* Stop peer. */
892 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
893 {
894 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000895 {
896 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
897 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
898 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
899 }
paul718e3742002-12-13 20:15:29 +0000900 else
901 BGP_EVENT_ADD (peer, BGP_Stop);
902 }
903 type = peer_sort (peer);
904 peer->as = as;
905
paul848973c2003-08-13 00:32:49 +0000906 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
907 && ! bgp_confederation_peers_check (peer->bgp, as)
908 && peer->bgp->as != as)
909 peer->local_as = peer->bgp->confed_id;
910 else
911 peer->local_as = peer->bgp->as;
912
paul718e3742002-12-13 20:15:29 +0000913 /* Advertisement-interval reset */
914 if (peer_sort (peer) == BGP_PEER_IBGP)
915 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
916 else
917 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
918
919 /* TTL reset */
920 if (peer_sort (peer) == BGP_PEER_IBGP)
921 peer->ttl = 255;
922 else if (type == BGP_PEER_IBGP)
923 peer->ttl = 1;
924
925 /* reflector-client reset */
926 if (peer_sort (peer) != BGP_PEER_IBGP)
927 {
928 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
929 PEER_FLAG_REFLECTOR_CLIENT);
930 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
931 PEER_FLAG_REFLECTOR_CLIENT);
932 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
933 PEER_FLAG_REFLECTOR_CLIENT);
934 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
935 PEER_FLAG_REFLECTOR_CLIENT);
936 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
937 PEER_FLAG_REFLECTOR_CLIENT);
938 }
939
940 /* local-as reset */
941 if (peer_sort (peer) != BGP_PEER_EBGP)
942 {
943 peer->change_local_as = 0;
944 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
945 }
946}
947
948/* If peer does not exist, create new one. If peer already exists,
949 set AS number to the peer. */
950int
951peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
952 afi_t afi, safi_t safi)
953{
954 struct peer *peer;
955 as_t local_as;
956
957 peer = peer_lookup (bgp, su);
958
959 if (peer)
960 {
961 /* When this peer is a member of peer-group. */
962 if (peer->group)
963 {
964 if (peer->group->conf->as)
965 {
966 /* Return peer group's AS number. */
967 *as = peer->group->conf->as;
968 return BGP_ERR_PEER_GROUP_MEMBER;
969 }
970 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
971 {
972 if (bgp->as != *as)
973 {
974 *as = peer->as;
975 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
976 }
977 }
978 else
979 {
980 if (bgp->as == *as)
981 {
982 *as = peer->as;
983 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
984 }
985 }
986 }
987
988 /* Existing peer's AS number change. */
989 if (peer->as != *as)
990 peer_as_change (peer, *as);
991 }
992 else
993 {
994
995 /* If the peer is not part of our confederation, and its not an
996 iBGP peer then spoof the source AS */
997 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
998 && ! bgp_confederation_peers_check (bgp, *as)
999 && bgp->as != *as)
1000 local_as = bgp->confed_id;
1001 else
1002 local_as = bgp->as;
1003
1004 /* If this is IPv4 unicast configuration and "no bgp default
1005 ipv4-unicast" is specified. */
1006
1007 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1008 && afi == AFI_IP && safi == SAFI_UNICAST)
1009 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1010 else
1011 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1012 }
1013
1014 return 0;
1015}
1016
1017/* Activate the peer or peer group for specified AFI and SAFI. */
1018int
1019peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1020{
1021 int active;
1022
1023 if (peer->afc[afi][safi])
1024 return 0;
1025
1026 /* Activate the address family configuration. */
1027 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1028 peer->afc[afi][safi] = 1;
1029 else
1030 {
1031 active = peer_active (peer);
1032
1033 peer->afc[afi][safi] = 1;
1034
1035 if (! active && peer_active (peer))
1036 bgp_timer_set (peer);
1037 else
1038 {
1039 if (peer->status == Established)
1040 {
1041 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1042 {
1043 peer->afc_adv[afi][safi] = 1;
1044 bgp_capability_send (peer, afi, safi,
1045 CAPABILITY_CODE_MP,
1046 CAPABILITY_ACTION_SET);
1047 if (peer->afc_recv[afi][safi])
1048 {
1049 peer->afc_nego[afi][safi] = 1;
1050 bgp_announce_route (peer, afi, safi);
1051 }
1052 }
1053 else
hassoe0701b72004-05-20 09:19:34 +00001054 {
1055 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1056 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1057 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1058 }
paul718e3742002-12-13 20:15:29 +00001059 }
1060 }
1061 }
1062 return 0;
1063}
1064
1065int
1066peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1067{
1068 struct peer_group *group;
1069 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001070 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001071
1072 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1073 {
1074 group = peer->group;
1075
paul1eb8ef22005-04-07 07:30:20 +00001076 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001077 {
1078 if (peer1->af_group[afi][safi])
1079 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1080 }
1081 }
1082 else
1083 {
1084 if (peer->af_group[afi][safi])
1085 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1086 }
1087
1088 if (! peer->afc[afi][safi])
1089 return 0;
1090
1091 /* De-activate the address family configuration. */
1092 peer->afc[afi][safi] = 0;
1093 peer_af_flag_reset (peer, afi, safi);
1094
1095 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1096 {
1097 if (peer->status == Established)
1098 {
1099 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1100 {
1101 peer->afc_adv[afi][safi] = 0;
1102 peer->afc_nego[afi][safi] = 0;
1103
1104 if (peer_active_nego (peer))
1105 {
1106 bgp_capability_send (peer, afi, safi,
1107 CAPABILITY_CODE_MP,
1108 CAPABILITY_ACTION_UNSET);
1109 bgp_clear_route (peer, afi, safi);
1110 peer->pcount[afi][safi] = 0;
1111 }
1112 else
hassoe0701b72004-05-20 09:19:34 +00001113 {
1114 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1115 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1116 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1117 }
paul718e3742002-12-13 20:15:29 +00001118 }
1119 else
hassoe0701b72004-05-20 09:19:34 +00001120 {
1121 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1122 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1123 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1124 }
paul718e3742002-12-13 20:15:29 +00001125 }
1126 }
1127 return 0;
1128}
1129
hasso93406d82005-02-02 14:40:33 +00001130void
1131peer_nsf_stop (struct peer *peer)
1132{
1133 afi_t afi;
1134 safi_t safi;
1135
1136 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1137 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1138
1139 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1140 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1141 peer->nsf[afi][safi] = 0;
1142
1143 if (peer->t_gr_restart)
1144 {
1145 BGP_TIMER_OFF (peer->t_gr_restart);
1146 if (BGP_DEBUG (events, EVENTS))
1147 zlog_debug ("%s graceful restart timer stopped", peer->host);
1148 }
1149 if (peer->t_gr_stale)
1150 {
1151 BGP_TIMER_OFF (peer->t_gr_stale);
1152 if (BGP_DEBUG (events, EVENTS))
1153 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1154 }
1155 bgp_clear_route_all (peer);
1156}
1157
Paul Jakmaca058a32006-09-14 02:58:49 +00001158/* Delete peer from confguration.
1159 *
1160 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1161 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1162 *
1163 * This function /should/ take care to be idempotent, to guard against
1164 * it being called multiple times through stray events that come in
1165 * that happen to result in this function being called again. That
1166 * said, getting here for a "Deleted" peer is a bug in the neighbour
1167 * FSM.
1168 */
paul718e3742002-12-13 20:15:29 +00001169int
1170peer_delete (struct peer *peer)
1171{
1172 int i;
1173 afi_t afi;
1174 safi_t safi;
1175 struct bgp *bgp;
1176 struct bgp_filter *filter;
1177
Paul Jakmaca058a32006-09-14 02:58:49 +00001178 assert (peer->status != Deleted);
1179
paul718e3742002-12-13 20:15:29 +00001180 bgp = peer->bgp;
1181
hasso93406d82005-02-02 14:40:33 +00001182 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1183 peer_nsf_stop (peer);
1184
paul718e3742002-12-13 20:15:29 +00001185 /* If this peer belongs to peer group. Clearn up the
1186 relationship. */
1187 if (peer->group)
1188 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001189 struct listnode *pn;
1190
1191 if ((pn = listnode_lookup (peer->group->peer, peer)))
1192 {
1193 peer = peer_unlock (peer); /* group->peer list reference */
1194 list_delete_node (peer->group->peer, pn);
1195 }
paul718e3742002-12-13 20:15:29 +00001196 peer->group = NULL;
1197 }
paul200df112005-06-01 11:17:05 +00001198
paul718e3742002-12-13 20:15:29 +00001199 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001200 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1201 * executed after peer structure is deleted.
1202 */
hassoe0701b72004-05-20 09:19:34 +00001203 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001204 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001205 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001206
1207 /* Password configuration */
1208 if (peer->password)
1209 {
1210 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1211 peer->password = NULL;
1212
1213 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1214 bgp_md5_set (peer);
1215 }
1216
Paul Jakmaca058a32006-09-14 02:58:49 +00001217 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001218
paul718e3742002-12-13 20:15:29 +00001219 /* Delete from all peer list. */
1220 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001221 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001222 struct listnode *pn;
paul200df112005-06-01 11:17:05 +00001223
Paul Jakmaca058a32006-09-14 02:58:49 +00001224 if ((pn = listnode_lookup (bgp->peer, peer)))
1225 {
1226 peer_unlock (peer); /* bgp peer list reference */
1227 list_delete_node (bgp->peer, pn);
1228 }
1229
1230 if (peer_rsclient_active (peer)
1231 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001232 {
1233 peer_unlock (peer); /* rsclient list reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001234 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001235 }
paulfee0f4c2004-09-13 05:12:46 +00001236 }
1237
1238 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1239 member of a peer_group. */
1240 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1241 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1242 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001243 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001244
paul200df112005-06-01 11:17:05 +00001245 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001246 if (peer->ibuf)
1247 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001248 if (peer->obuf)
1249 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001250 if (peer->work)
1251 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001252 peer->obuf = NULL;
1253 peer->work = peer->ibuf = NULL;
1254
paul718e3742002-12-13 20:15:29 +00001255 /* Local and remote addresses. */
1256 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001257 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001258 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001259 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001260 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001261
paul718e3742002-12-13 20:15:29 +00001262 /* Free filter related memory. */
1263 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1264 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1265 {
1266 filter = &peer->filter[afi][safi];
1267
1268 for (i = FILTER_IN; i < FILTER_MAX; i++)
1269 {
1270 if (filter->dlist[i].name)
1271 free (filter->dlist[i].name);
1272 if (filter->plist[i].name)
1273 free (filter->plist[i].name);
1274 if (filter->aslist[i].name)
1275 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001276
1277 filter->dlist[i].name = NULL;
1278 filter->plist[i].name = NULL;
1279 filter->aslist[i].name = NULL;
1280 }
1281 for (i = RMAP_IN; i < RMAP_MAX; i++)
1282 {
paul718e3742002-12-13 20:15:29 +00001283 if (filter->map[i].name)
1284 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001285 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001286 }
1287
1288 if (filter->usmap.name)
1289 free (filter->usmap.name);
1290
1291 if (peer->default_rmap[afi][safi].name)
1292 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001293
1294 filter->usmap.name = NULL;
1295 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001296 }
paul200df112005-06-01 11:17:05 +00001297
1298 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001299
1300 return 0;
1301}
1302
paul94f2b392005-06-28 12:44:16 +00001303static int
paul718e3742002-12-13 20:15:29 +00001304peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1305{
1306 return strcmp (g1->name, g2->name);
1307}
1308
1309/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001310static int
paul718e3742002-12-13 20:15:29 +00001311peer_group_active (struct peer *peer)
1312{
1313 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1314 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1315 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1316 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1317 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1318 return 1;
1319 return 0;
1320}
1321
1322/* Peer group cofiguration. */
1323static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001324peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001325{
1326 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1327 sizeof (struct peer_group));
1328}
1329
paul94f2b392005-06-28 12:44:16 +00001330static void
paul718e3742002-12-13 20:15:29 +00001331peer_group_free (struct peer_group *group)
1332{
1333 XFREE (MTYPE_PEER_GROUP, group);
1334}
1335
1336struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001337peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001338{
1339 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001340 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001341
paul1eb8ef22005-04-07 07:30:20 +00001342 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001343 {
1344 if (strcmp (group->name, name) == 0)
1345 return group;
1346 }
1347 return NULL;
1348}
1349
1350struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001351peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001352{
1353 struct peer_group *group;
1354
1355 group = peer_group_lookup (bgp, name);
1356 if (group)
1357 return group;
1358
1359 group = peer_group_new ();
1360 group->bgp = bgp;
1361 group->name = strdup (name);
1362 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001363 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001364 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1365 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1366 group->conf->host = strdup (name);
paul718e3742002-12-13 20:15:29 +00001367 group->conf->group = group;
1368 group->conf->as = 0;
1369 group->conf->ttl = 1;
1370 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1371 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1372 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1373 group->conf->keepalive = 0;
1374 group->conf->holdtime = 0;
1375 group->conf->connect = 0;
1376 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1377 listnode_add_sort (bgp->group, group);
1378
1379 return 0;
1380}
1381
paul94f2b392005-06-28 12:44:16 +00001382static void
paul718e3742002-12-13 20:15:29 +00001383peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1384 afi_t afi, safi_t safi)
1385{
1386 int in = FILTER_IN;
1387 int out = FILTER_OUT;
1388 struct peer *conf;
1389 struct bgp_filter *pfilter;
1390 struct bgp_filter *gfilter;
1391
1392 conf = group->conf;
1393 pfilter = &peer->filter[afi][safi];
1394 gfilter = &conf->filter[afi][safi];
1395
1396 /* remote-as */
1397 if (conf->as)
1398 peer->as = conf->as;
1399
1400 /* remote-as */
1401 if (conf->change_local_as)
1402 peer->change_local_as = conf->change_local_as;
1403
1404 /* TTL */
1405 peer->ttl = conf->ttl;
1406
1407 /* Weight */
1408 peer->weight = conf->weight;
1409
1410 /* peer flags apply */
1411 peer->flags = conf->flags;
1412 /* peer af_flags apply */
1413 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1414 /* peer config apply */
1415 peer->config = conf->config;
1416
1417 /* peer timers apply */
1418 peer->holdtime = conf->holdtime;
1419 peer->keepalive = conf->keepalive;
1420 peer->connect = conf->connect;
1421 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1422 peer->v_connect = conf->connect;
1423 else
1424 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1425
1426 /* advertisement-interval reset */
1427 if (peer_sort (peer) == BGP_PEER_IBGP)
1428 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1429 else
1430 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1431
Paul Jakma0df7c912008-07-21 21:02:49 +00001432 /* password apply */
1433 if (peer->password)
1434 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1435
1436 if (conf->password)
1437 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1438 else
1439 peer->password = NULL;
1440
1441 bgp_md5_set (peer);
1442
paul718e3742002-12-13 20:15:29 +00001443 /* maximum-prefix */
1444 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001445 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001446 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001447
1448 /* allowas-in */
1449 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1450
paulfee0f4c2004-09-13 05:12:46 +00001451 /* route-server-client */
1452 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1453 {
1454 /* Make peer's RIB point to group's RIB. */
1455 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1456
1457 /* Import policy. */
1458 if (pfilter->map[RMAP_IMPORT].name)
1459 free (pfilter->map[RMAP_IMPORT].name);
1460 if (gfilter->map[RMAP_IMPORT].name)
1461 {
1462 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1463 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1464 }
1465 else
1466 {
1467 pfilter->map[RMAP_IMPORT].name = NULL;
1468 pfilter->map[RMAP_IMPORT].map = NULL;
1469 }
1470
1471 /* Export policy. */
1472 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1473 {
1474 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1475 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1476 }
1477 }
1478
paul718e3742002-12-13 20:15:29 +00001479 /* default-originate route-map */
1480 if (conf->default_rmap[afi][safi].name)
1481 {
1482 if (peer->default_rmap[afi][safi].name)
1483 free (peer->default_rmap[afi][safi].name);
1484 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1485 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1486 }
1487
1488 /* update-source apply */
1489 if (conf->update_source)
1490 {
1491 if (peer->update_source)
1492 sockunion_free (peer->update_source);
1493 if (peer->update_if)
1494 {
1495 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1496 peer->update_if = NULL;
1497 }
1498 peer->update_source = sockunion_dup (conf->update_source);
1499 }
1500 else if (conf->update_if)
1501 {
1502 if (peer->update_if)
1503 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1504 if (peer->update_source)
1505 {
1506 sockunion_free (peer->update_source);
1507 peer->update_source = NULL;
1508 }
1509 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1510 }
1511
1512 /* inbound filter apply */
1513 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1514 {
1515 if (pfilter->dlist[in].name)
1516 free (pfilter->dlist[in].name);
1517 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1518 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1519 }
1520 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1521 {
1522 if (pfilter->plist[in].name)
1523 free (pfilter->plist[in].name);
1524 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1525 pfilter->plist[in].plist = gfilter->plist[in].plist;
1526 }
1527 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1528 {
1529 if (pfilter->aslist[in].name)
1530 free (pfilter->aslist[in].name);
1531 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1532 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1533 }
paulfee0f4c2004-09-13 05:12:46 +00001534 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001535 {
paulfee0f4c2004-09-13 05:12:46 +00001536 if (pfilter->map[RMAP_IN].name)
1537 free (pfilter->map[RMAP_IN].name);
1538 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1539 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001540 }
1541
1542 /* outbound filter apply */
1543 if (gfilter->dlist[out].name)
1544 {
1545 if (pfilter->dlist[out].name)
1546 free (pfilter->dlist[out].name);
1547 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1548 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1549 }
1550 else
1551 {
1552 if (pfilter->dlist[out].name)
1553 free (pfilter->dlist[out].name);
1554 pfilter->dlist[out].name = NULL;
1555 pfilter->dlist[out].alist = NULL;
1556 }
1557 if (gfilter->plist[out].name)
1558 {
1559 if (pfilter->plist[out].name)
1560 free (pfilter->plist[out].name);
1561 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1562 pfilter->plist[out].plist = gfilter->plist[out].plist;
1563 }
1564 else
1565 {
1566 if (pfilter->plist[out].name)
1567 free (pfilter->plist[out].name);
1568 pfilter->plist[out].name = NULL;
1569 pfilter->plist[out].plist = NULL;
1570 }
1571 if (gfilter->aslist[out].name)
1572 {
1573 if (pfilter->aslist[out].name)
1574 free (pfilter->aslist[out].name);
1575 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1576 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1577 }
1578 else
1579 {
1580 if (pfilter->aslist[out].name)
1581 free (pfilter->aslist[out].name);
1582 pfilter->aslist[out].name = NULL;
1583 pfilter->aslist[out].aslist = NULL;
1584 }
paulfee0f4c2004-09-13 05:12:46 +00001585 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001586 {
paulfee0f4c2004-09-13 05:12:46 +00001587 if (pfilter->map[RMAP_OUT].name)
1588 free (pfilter->map[RMAP_OUT].name);
1589 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1590 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001591 }
1592 else
1593 {
paulfee0f4c2004-09-13 05:12:46 +00001594 if (pfilter->map[RMAP_OUT].name)
1595 free (pfilter->map[RMAP_OUT].name);
1596 pfilter->map[RMAP_OUT].name = NULL;
1597 pfilter->map[RMAP_OUT].map = NULL;
1598 }
1599
1600 /* RS-client's import/export route-maps. */
1601 if (gfilter->map[RMAP_IMPORT].name)
1602 {
1603 if (pfilter->map[RMAP_IMPORT].name)
1604 free (pfilter->map[RMAP_IMPORT].name);
1605 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1606 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1607 }
1608 else
1609 {
1610 if (pfilter->map[RMAP_IMPORT].name)
1611 free (pfilter->map[RMAP_IMPORT].name);
1612 pfilter->map[RMAP_IMPORT].name = NULL;
1613 pfilter->map[RMAP_IMPORT].map = NULL;
1614 }
1615 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1616 {
1617 if (pfilter->map[RMAP_EXPORT].name)
1618 free (pfilter->map[RMAP_EXPORT].name);
1619 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1620 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001621 }
1622
1623 if (gfilter->usmap.name)
1624 {
1625 if (pfilter->usmap.name)
1626 free (pfilter->usmap.name);
1627 pfilter->usmap.name = strdup (gfilter->usmap.name);
1628 pfilter->usmap.map = gfilter->usmap.map;
1629 }
1630 else
1631 {
1632 if (pfilter->usmap.name)
1633 free (pfilter->usmap.name);
1634 pfilter->usmap.name = NULL;
1635 pfilter->usmap.map = NULL;
1636 }
1637}
1638
1639/* Peer group's remote AS configuration. */
1640int
paulfd79ac92004-10-13 05:06:08 +00001641peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001642{
1643 struct peer_group *group;
1644 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001645 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001646
1647 group = peer_group_lookup (bgp, group_name);
1648 if (! group)
1649 return -1;
1650
1651 if (group->conf->as == *as)
1652 return 0;
1653
1654 /* When we setup peer-group AS number all peer group member's AS
1655 number must be updated to same number. */
1656 peer_as_change (group->conf, *as);
1657
paul1eb8ef22005-04-07 07:30:20 +00001658 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001659 {
1660 if (peer->as != *as)
1661 peer_as_change (peer, *as);
1662 }
1663
1664 return 0;
1665}
1666
1667int
1668peer_group_delete (struct peer_group *group)
1669{
1670 struct bgp *bgp;
1671 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001672 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001673
1674 bgp = group->bgp;
1675
paul1eb8ef22005-04-07 07:30:20 +00001676 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001677 {
1678 peer->group = NULL;
1679 peer_delete (peer);
1680 }
1681 list_delete (group->peer);
1682
1683 free (group->name);
1684 group->name = NULL;
1685
1686 group->conf->group = NULL;
1687 peer_delete (group->conf);
1688
1689 /* Delete from all peer_group list. */
1690 listnode_delete (bgp->group, group);
1691
1692 peer_group_free (group);
1693
1694 return 0;
1695}
1696
1697int
1698peer_group_remote_as_delete (struct peer_group *group)
1699{
1700 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001701 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001702
1703 if (! group->conf->as)
1704 return 0;
1705
paul1eb8ef22005-04-07 07:30:20 +00001706 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001707 {
1708 peer->group = NULL;
1709 peer_delete (peer);
1710 }
1711 list_delete_all_node (group->peer);
1712
1713 group->conf->as = 0;
1714
1715 return 0;
1716}
1717
1718/* Bind specified peer to peer group. */
1719int
1720peer_group_bind (struct bgp *bgp, union sockunion *su,
1721 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1722{
1723 struct peer *peer;
1724 int first_member = 0;
1725
1726 /* Check peer group's address family. */
1727 if (! group->conf->afc[afi][safi])
1728 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1729
1730 /* Lookup the peer. */
1731 peer = peer_lookup (bgp, su);
1732
1733 /* Create a new peer. */
1734 if (! peer)
1735 {
1736 if (! group->conf->as)
1737 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1738
1739 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1740 peer->group = group;
1741 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001742
Paul Jakmaca058a32006-09-14 02:58:49 +00001743 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001744 listnode_add (group->peer, peer);
1745 peer_group2peer_config_copy (group, peer, afi, safi);
1746
1747 return 0;
1748 }
1749
1750 /* When the peer already belongs to peer group, check the consistency. */
1751 if (peer->af_group[afi][safi])
1752 {
1753 if (strcmp (peer->group->name, group->name) != 0)
1754 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1755
1756 return 0;
1757 }
1758
1759 /* Check current peer group configuration. */
1760 if (peer_group_active (peer)
1761 && strcmp (peer->group->name, group->name) != 0)
1762 return BGP_ERR_PEER_GROUP_MISMATCH;
1763
1764 if (! group->conf->as)
1765 {
1766 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1767 && peer_sort (group->conf) != peer_sort (peer))
1768 {
1769 if (as)
1770 *as = peer->as;
1771 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1772 }
1773
1774 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1775 first_member = 1;
1776 }
1777
1778 peer->af_group[afi][safi] = 1;
1779 peer->afc[afi][safi] = 1;
1780 if (! peer->group)
1781 {
1782 peer->group = group;
paul200df112005-06-01 11:17:05 +00001783
Paul Jakmaca058a32006-09-14 02:58:49 +00001784 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001785 listnode_add (group->peer, peer);
1786 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001787 else
1788 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001789
1790 if (first_member)
1791 {
1792 /* Advertisement-interval reset */
1793 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1794 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1795 else
1796 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1797
1798 /* ebgp-multihop reset */
1799 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1800 group->conf->ttl = 255;
1801
1802 /* local-as reset */
1803 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1804 {
1805 group->conf->change_local_as = 0;
1806 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1807 }
1808 }
paulfee0f4c2004-09-13 05:12:46 +00001809
1810 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1811 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 struct listnode *pn;
1813
paulfee0f4c2004-09-13 05:12:46 +00001814 /* If it's not configured as RSERVER_CLIENT in any other address
1815 family, without being member of a peer_group, remove it from
1816 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001817 if (! peer_rsclient_active (peer)
1818 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001819 {
1820 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001821 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001822 }
paulfee0f4c2004-09-13 05:12:46 +00001823
Paul Jakmab608d5b2008-07-02 02:12:07 +00001824 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001825
1826 /* Import policy. */
1827 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1828 {
1829 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1830 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1831 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1832 }
1833
1834 /* Export policy. */
1835 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1836 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1837 {
1838 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1839 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1840 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1841 }
1842 }
1843
paul718e3742002-12-13 20:15:29 +00001844 peer_group2peer_config_copy (group, peer, afi, safi);
1845
1846 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001847 {
1848 peer->last_reset = PEER_DOWN_RMAP_BIND;
1849 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1850 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1851 }
paul718e3742002-12-13 20:15:29 +00001852 else
1853 BGP_EVENT_ADD (peer, BGP_Stop);
1854
1855 return 0;
1856}
1857
1858int
1859peer_group_unbind (struct bgp *bgp, struct peer *peer,
1860 struct peer_group *group, afi_t afi, safi_t safi)
1861{
1862 if (! peer->af_group[afi][safi])
1863 return 0;
1864
1865 if (group != peer->group)
1866 return BGP_ERR_PEER_GROUP_MISMATCH;
1867
1868 peer->af_group[afi][safi] = 0;
1869 peer->afc[afi][safi] = 0;
1870 peer_af_flag_reset (peer, afi, safi);
1871
paulfee0f4c2004-09-13 05:12:46 +00001872 if (peer->rib[afi][safi])
1873 peer->rib[afi][safi] = NULL;
1874
paul718e3742002-12-13 20:15:29 +00001875 if (! peer_group_active (peer))
1876 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001877 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001878 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001879 listnode_delete (group->peer, peer);
1880 peer->group = NULL;
1881 if (group->conf->as)
1882 {
1883 peer_delete (peer);
1884 return 0;
1885 }
1886 peer_global_config_reset (peer);
1887 }
1888
1889 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001890 {
1891 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1892 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1893 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1894 }
paul718e3742002-12-13 20:15:29 +00001895 else
1896 BGP_EVENT_ADD (peer, BGP_Stop);
1897
1898 return 0;
1899}
1900
1901/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001902static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001903bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001904{
1905 struct bgp *bgp;
1906 afi_t afi;
1907 safi_t safi;
1908
paul200df112005-06-01 11:17:05 +00001909 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1910 return NULL;
1911
Paul Jakma6f585442006-10-22 19:13:07 +00001912 bgp->peer_self = peer_new (bgp);
paulfd79ac92004-10-13 05:06:08 +00001913 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001914
1915 bgp->peer = list_new ();
1916 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1917
1918 bgp->group = list_new ();
1919 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1920
paulfee0f4c2004-09-13 05:12:46 +00001921 bgp->rsclient = list_new ();
1922 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1923
paul718e3742002-12-13 20:15:29 +00001924 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1925 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1926 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001927 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1928 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1929 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001930 }
1931
1932 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1933 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1934 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001935 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1936 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001937
1938 bgp->as = *as;
1939
1940 if (name)
1941 bgp->name = strdup (name);
1942
1943 return bgp;
1944}
1945
1946/* Return first entry of BGP. */
1947struct bgp *
paul94f2b392005-06-28 12:44:16 +00001948bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001949{
1950 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001951 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001952 return NULL;
1953}
1954
1955/* Lookup BGP entry. */
1956struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001957bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001958{
1959 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001960 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001961
paul1eb8ef22005-04-07 07:30:20 +00001962 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001963 if (bgp->as == as
1964 && ((bgp->name == NULL && name == NULL)
1965 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1966 return bgp;
1967 return NULL;
1968}
1969
1970/* Lookup BGP structure by view name. */
1971struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001972bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001973{
1974 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001975 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001976
paul1eb8ef22005-04-07 07:30:20 +00001977 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001978 if ((bgp->name == NULL && name == NULL)
1979 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1980 return bgp;
1981 return NULL;
1982}
1983
1984/* Called from VTY commands. */
1985int
paulfd79ac92004-10-13 05:06:08 +00001986bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001987{
1988 struct bgp *bgp;
1989
1990 /* Multiple instance check. */
1991 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1992 {
1993 if (name)
1994 bgp = bgp_lookup_by_name (name);
1995 else
1996 bgp = bgp_get_default ();
1997
1998 /* Already exists. */
1999 if (bgp)
2000 {
2001 if (bgp->as != *as)
2002 {
2003 *as = bgp->as;
2004 return BGP_ERR_INSTANCE_MISMATCH;
2005 }
2006 *bgp_val = bgp;
2007 return 0;
2008 }
2009 }
2010 else
2011 {
2012 /* BGP instance name can not be specified for single instance. */
2013 if (name)
2014 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2015
2016 /* Get default BGP structure if exists. */
2017 bgp = bgp_get_default ();
2018
2019 if (bgp)
2020 {
2021 if (bgp->as != *as)
2022 {
2023 *as = bgp->as;
2024 return BGP_ERR_AS_MISMATCH;
2025 }
2026 *bgp_val = bgp;
2027 return 0;
2028 }
2029 }
2030
2031 bgp = bgp_create (as, name);
2032 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002033 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002034 *bgp_val = bgp;
2035
2036 return 0;
2037}
2038
2039/* Delete BGP instance. */
2040int
2041bgp_delete (struct bgp *bgp)
2042{
2043 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002044 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002045 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002046 struct listnode *next;
2047 afi_t afi;
2048 safi_t safi;
2049 int i;
2050
2051 /* Delete static route. */
2052 bgp_static_delete (bgp);
2053
2054 /* Unset redistribution. */
2055 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2056 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2057 if (i != ZEBRA_ROUTE_BGP)
2058 bgp_redistribute_unset (bgp, afi, i);
2059
hassob6b7cff2005-05-26 08:29:07 +00002060 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2061 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002062 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002063
paul1eb8ef22005-04-07 07:30:20 +00002064 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2065 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002066 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002067
hasso54a6ed32005-05-26 22:12:33 +00002068 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2069 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002070 list_delete (bgp->rsclient);
2071
paul718e3742002-12-13 20:15:29 +00002072 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002073
paul718e3742002-12-13 20:15:29 +00002074 if (bgp->name)
2075 free (bgp->name);
2076
2077 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2078 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2079 {
2080 if (bgp->route[afi][safi])
2081 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2082 if (bgp->aggregate[afi][safi])
2083 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2084 if (bgp->rib[afi][safi])
2085 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2086 }
2087 XFREE (MTYPE_BGP, bgp);
2088
2089 return 0;
2090}
2091
2092struct peer *
2093peer_lookup (struct bgp *bgp, union sockunion *su)
2094{
2095 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002096 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002097
2098 if (! bgp)
2099 bgp = bgp_get_default ();
2100
2101 if (! bgp)
2102 return NULL;
2103
paul1eb8ef22005-04-07 07:30:20 +00002104 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002105 {
pauleb821182004-05-01 08:44:08 +00002106 if (sockunion_same (&peer->su, su)
2107 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2108 return peer;
paul718e3742002-12-13 20:15:29 +00002109 }
2110 return NULL;
2111}
2112
2113struct peer *
2114peer_lookup_with_open (union sockunion *su, as_t remote_as,
2115 struct in_addr *remote_id, int *as)
2116{
2117 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002118 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002119 struct bgp *bgp;
2120
2121 bgp = bgp_get_default ();
2122 if (! bgp)
2123 return NULL;
2124
paul1eb8ef22005-04-07 07:30:20 +00002125 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002126 {
pauleb821182004-05-01 08:44:08 +00002127 if (sockunion_same (&peer->su, su)
2128 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2129 {
2130 if (peer->as == remote_as
2131 && peer->remote_id.s_addr == remote_id->s_addr)
2132 return peer;
2133 if (peer->as == remote_as)
2134 *as = 1;
2135 }
paul718e3742002-12-13 20:15:29 +00002136 }
paul1eb8ef22005-04-07 07:30:20 +00002137 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002138 {
pauleb821182004-05-01 08:44:08 +00002139 if (sockunion_same (&peer->su, su)
2140 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2141 {
2142 if (peer->as == remote_as
2143 && peer->remote_id.s_addr == 0)
2144 return peer;
2145 if (peer->as == remote_as)
2146 *as = 1;
2147 }
paul718e3742002-12-13 20:15:29 +00002148 }
2149 return NULL;
2150}
2151
2152/* If peer is configured at least one address family return 1. */
2153int
2154peer_active (struct peer *peer)
2155{
2156 if (peer->afc[AFI_IP][SAFI_UNICAST]
2157 || peer->afc[AFI_IP][SAFI_MULTICAST]
2158 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2159 || peer->afc[AFI_IP6][SAFI_UNICAST]
2160 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2161 return 1;
2162 return 0;
2163}
2164
2165/* If peer is negotiated at least one address family return 1. */
2166int
2167peer_active_nego (struct peer *peer)
2168{
2169 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2170 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2171 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2172 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2173 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2174 return 1;
2175 return 0;
2176}
2177
2178/* peer_flag_change_type. */
2179enum peer_change_type
2180{
2181 peer_change_none,
2182 peer_change_reset,
2183 peer_change_reset_in,
2184 peer_change_reset_out,
2185};
2186
paul94f2b392005-06-28 12:44:16 +00002187static void
paul718e3742002-12-13 20:15:29 +00002188peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2189 enum peer_change_type type)
2190{
2191 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2192 return;
2193
2194 if (type == peer_change_reset)
2195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2196 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2197 else if (type == peer_change_reset_in)
2198 {
2199 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2200 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2201 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2202 else
2203 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2204 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2205 }
2206 else if (type == peer_change_reset_out)
2207 bgp_announce_route (peer, afi, safi);
2208}
2209
2210struct peer_flag_action
2211{
2212 /* Peer's flag. */
2213 u_int32_t flag;
2214
2215 /* This flag can be set for peer-group member. */
2216 u_char not_for_member;
2217
2218 /* Action when the flag is changed. */
2219 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002220
2221 /* Peer down cause */
2222 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002223};
2224
2225struct peer_flag_action peer_flag_action_list[] =
2226 {
2227 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2228 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2229 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2230 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2231 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002232 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002233 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002234 { 0, 0, 0 }
2235 };
2236
2237struct peer_flag_action peer_af_flag_action_list[] =
2238 {
2239 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2240 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2241 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2242 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2243 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2244 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2245 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2246 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2247 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2248 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2249 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2250 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2251 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002252 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002253 { 0, 0, 0 }
2254 };
2255
2256/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002257static int
paul718e3742002-12-13 20:15:29 +00002258peer_flag_action_set (struct peer_flag_action *action_list, int size,
2259 struct peer_flag_action *action, u_int32_t flag)
2260{
2261 int i;
2262 int found = 0;
2263 int reset_in = 0;
2264 int reset_out = 0;
2265 struct peer_flag_action *match = NULL;
2266
2267 /* Check peer's frag action. */
2268 for (i = 0; i < size; i++)
2269 {
2270 match = &action_list[i];
2271
2272 if (match->flag == 0)
2273 break;
2274
2275 if (match->flag & flag)
2276 {
2277 found = 1;
2278
2279 if (match->type == peer_change_reset_in)
2280 reset_in = 1;
2281 if (match->type == peer_change_reset_out)
2282 reset_out = 1;
2283 if (match->type == peer_change_reset)
2284 {
2285 reset_in = 1;
2286 reset_out = 1;
2287 }
2288 if (match->not_for_member)
2289 action->not_for_member = 1;
2290 }
2291 }
2292
2293 /* Set peer clear type. */
2294 if (reset_in && reset_out)
2295 action->type = peer_change_reset;
2296 else if (reset_in)
2297 action->type = peer_change_reset_in;
2298 else if (reset_out)
2299 action->type = peer_change_reset_out;
2300 else
2301 action->type = peer_change_none;
2302
2303 return found;
2304}
2305
paul94f2b392005-06-28 12:44:16 +00002306static void
paul718e3742002-12-13 20:15:29 +00002307peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2308{
2309 if (flag == PEER_FLAG_SHUTDOWN)
2310 {
2311 if (CHECK_FLAG (peer->flags, flag))
2312 {
hasso93406d82005-02-02 14:40:33 +00002313 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2314 peer_nsf_stop (peer);
2315
hasso0a486e52005-02-01 20:57:17 +00002316 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2317 if (peer->t_pmax_restart)
2318 {
2319 BGP_TIMER_OFF (peer->t_pmax_restart);
2320 if (BGP_DEBUG (events, EVENTS))
2321 zlog_debug ("%s Maximum-prefix restart timer canceled",
2322 peer->host);
2323 }
2324
hasso93406d82005-02-02 14:40:33 +00002325 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2326 peer_nsf_stop (peer);
2327
paul718e3742002-12-13 20:15:29 +00002328 if (peer->status == Established)
2329 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2330 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2331 else
2332 BGP_EVENT_ADD (peer, BGP_Stop);
2333 }
2334 else
2335 {
2336 peer->v_start = BGP_INIT_START_TIMER;
2337 BGP_EVENT_ADD (peer, BGP_Stop);
2338 }
2339 }
2340 else if (peer->status == Established)
2341 {
hassoc9502432005-02-01 22:01:48 +00002342 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2343 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2344 else if (flag == PEER_FLAG_PASSIVE)
2345 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002346 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002347 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002348
hassoc9502432005-02-01 22:01:48 +00002349 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2350 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002351 }
2352 else
2353 BGP_EVENT_ADD (peer, BGP_Stop);
2354}
2355
2356/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002357static int
paul718e3742002-12-13 20:15:29 +00002358peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2359{
2360 int found;
2361 int size;
2362 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002363 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002364 struct peer_flag_action action;
2365
2366 memset (&action, 0, sizeof (struct peer_flag_action));
2367 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2368
2369 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2370
2371 /* No flag action is found. */
2372 if (! found)
2373 return BGP_ERR_INVALID_FLAG;
2374
2375 /* Not for peer-group member. */
2376 if (action.not_for_member && peer_group_active (peer))
2377 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2378
2379 /* When unset the peer-group member's flag we have to check
2380 peer-group configuration. */
2381 if (! set && peer_group_active (peer))
2382 if (CHECK_FLAG (peer->group->conf->flags, flag))
2383 {
2384 if (flag == PEER_FLAG_SHUTDOWN)
2385 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2386 else
2387 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2388 }
2389
2390 /* Flag conflict check. */
2391 if (set
2392 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2393 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2394 return BGP_ERR_PEER_FLAG_CONFLICT;
2395
2396 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2397 {
2398 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2399 return 0;
2400 if (! set && ! CHECK_FLAG (peer->flags, flag))
2401 return 0;
2402 }
2403
2404 if (set)
2405 SET_FLAG (peer->flags, flag);
2406 else
2407 UNSET_FLAG (peer->flags, flag);
2408
2409 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2410 {
2411 if (action.type == peer_change_reset)
2412 peer_flag_modify_action (peer, flag);
2413
2414 return 0;
2415 }
2416
2417 /* peer-group member updates. */
2418 group = peer->group;
2419
paul1eb8ef22005-04-07 07:30:20 +00002420 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002421 {
2422 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2423 continue;
2424
2425 if (! set && ! CHECK_FLAG (peer->flags, flag))
2426 continue;
2427
2428 if (set)
2429 SET_FLAG (peer->flags, flag);
2430 else
2431 UNSET_FLAG (peer->flags, flag);
2432
2433 if (action.type == peer_change_reset)
2434 peer_flag_modify_action (peer, flag);
2435 }
2436 return 0;
2437}
2438
2439int
2440peer_flag_set (struct peer *peer, u_int32_t flag)
2441{
2442 return peer_flag_modify (peer, flag, 1);
2443}
2444
2445int
2446peer_flag_unset (struct peer *peer, u_int32_t flag)
2447{
2448 return peer_flag_modify (peer, flag, 0);
2449}
2450
paul94f2b392005-06-28 12:44:16 +00002451static int
paul718e3742002-12-13 20:15:29 +00002452peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2453{
2454 if (peer->af_group[afi][safi])
2455 return 1;
2456 return 0;
2457}
2458
paul94f2b392005-06-28 12:44:16 +00002459static int
paul718e3742002-12-13 20:15:29 +00002460peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2461 int set)
2462{
2463 int found;
2464 int size;
paul1eb8ef22005-04-07 07:30:20 +00002465 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002466 struct peer_group *group;
2467 struct peer_flag_action action;
2468
2469 memset (&action, 0, sizeof (struct peer_flag_action));
2470 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2471
2472 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2473
2474 /* No flag action is found. */
2475 if (! found)
2476 return BGP_ERR_INVALID_FLAG;
2477
2478 /* Adress family must be activated. */
2479 if (! peer->afc[afi][safi])
2480 return BGP_ERR_PEER_INACTIVE;
2481
2482 /* Not for peer-group member. */
2483 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2484 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2485
2486 /* Spcecial check for reflector client. */
2487 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2488 && peer_sort (peer) != BGP_PEER_IBGP)
2489 return BGP_ERR_NOT_INTERNAL_PEER;
2490
2491 /* Spcecial check for remove-private-AS. */
2492 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2493 && peer_sort (peer) == BGP_PEER_IBGP)
2494 return BGP_ERR_REMOVE_PRIVATE_AS;
2495
2496 /* When unset the peer-group member's flag we have to check
2497 peer-group configuration. */
2498 if (! set && peer->af_group[afi][safi])
2499 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2500 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2501
2502 /* When current flag configuration is same as requested one. */
2503 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2504 {
2505 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2506 return 0;
2507 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2508 return 0;
2509 }
2510
2511 if (set)
2512 SET_FLAG (peer->af_flags[afi][safi], flag);
2513 else
2514 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2515
2516 /* Execute action when peer is established. */
2517 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2518 && peer->status == Established)
2519 {
2520 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2521 bgp_clear_adj_in (peer, afi, safi);
2522 else
hassoe0701b72004-05-20 09:19:34 +00002523 {
2524 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2525 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2526 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2527 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2528 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2529 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2530 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2531 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2532
2533 peer_change_action (peer, afi, safi, action.type);
2534 }
2535
paul718e3742002-12-13 20:15:29 +00002536 }
2537
2538 /* Peer group member updates. */
2539 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2540 {
2541 group = peer->group;
2542
paul1eb8ef22005-04-07 07:30:20 +00002543 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002544 {
2545 if (! peer->af_group[afi][safi])
2546 continue;
2547
2548 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2549 continue;
2550
2551 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2552 continue;
2553
2554 if (set)
2555 SET_FLAG (peer->af_flags[afi][safi], flag);
2556 else
2557 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2558
2559 if (peer->status == Established)
2560 {
2561 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2562 bgp_clear_adj_in (peer, afi, safi);
2563 else
hassoe0701b72004-05-20 09:19:34 +00002564 {
2565 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2566 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2567 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2568 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2569 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2570 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2571 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2572 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2573
2574 peer_change_action (peer, afi, safi, action.type);
2575 }
paul718e3742002-12-13 20:15:29 +00002576 }
2577 }
2578 }
2579 return 0;
2580}
2581
2582int
2583peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2584{
2585 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2586}
2587
2588int
2589peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2590{
2591 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2592}
2593
2594/* EBGP multihop configuration. */
2595int
2596peer_ebgp_multihop_set (struct peer *peer, int ttl)
2597{
2598 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002599 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002600
2601 if (peer_sort (peer) == BGP_PEER_IBGP)
2602 return 0;
2603
2604 peer->ttl = ttl;
2605
2606 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2607 {
pauleb821182004-05-01 08:44:08 +00002608 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2609 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002610 }
2611 else
2612 {
2613 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002614 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002615 {
2616 if (peer_sort (peer) == BGP_PEER_IBGP)
2617 continue;
paul718e3742002-12-13 20:15:29 +00002618
pauleb821182004-05-01 08:44:08 +00002619 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002620
pauleb821182004-05-01 08:44:08 +00002621 if (peer->fd >= 0)
2622 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2623 }
paul718e3742002-12-13 20:15:29 +00002624 }
2625 return 0;
2626}
2627
2628int
2629peer_ebgp_multihop_unset (struct peer *peer)
2630{
2631 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002632 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002633
2634 if (peer_sort (peer) == BGP_PEER_IBGP)
2635 return 0;
2636
2637 if (peer_group_active (peer))
2638 peer->ttl = peer->group->conf->ttl;
2639 else
2640 peer->ttl = 1;
2641
2642 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2643 {
pauleb821182004-05-01 08:44:08 +00002644 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2645 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002646 }
2647 else
2648 {
2649 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002650 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002651 {
2652 if (peer_sort (peer) == BGP_PEER_IBGP)
2653 continue;
paul718e3742002-12-13 20:15:29 +00002654
pauleb821182004-05-01 08:44:08 +00002655 peer->ttl = 1;
2656
2657 if (peer->fd >= 0)
2658 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2659 }
paul718e3742002-12-13 20:15:29 +00002660 }
2661 return 0;
2662}
2663
2664/* Neighbor description. */
2665int
2666peer_description_set (struct peer *peer, char *desc)
2667{
2668 if (peer->desc)
2669 XFREE (MTYPE_PEER_DESC, peer->desc);
2670
2671 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2672
2673 return 0;
2674}
2675
2676int
2677peer_description_unset (struct peer *peer)
2678{
2679 if (peer->desc)
2680 XFREE (MTYPE_PEER_DESC, peer->desc);
2681
2682 peer->desc = NULL;
2683
2684 return 0;
2685}
2686
2687/* Neighbor update-source. */
2688int
paulfd79ac92004-10-13 05:06:08 +00002689peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002690{
2691 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002692 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002693
2694 if (peer->update_if)
2695 {
2696 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2697 && strcmp (peer->update_if, ifname) == 0)
2698 return 0;
2699
2700 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2701 peer->update_if = NULL;
2702 }
2703
2704 if (peer->update_source)
2705 {
2706 sockunion_free (peer->update_source);
2707 peer->update_source = NULL;
2708 }
2709
2710 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2711
2712 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2713 {
2714 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002715 {
2716 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2717 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2718 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2719 }
paul718e3742002-12-13 20:15:29 +00002720 else
2721 BGP_EVENT_ADD (peer, BGP_Stop);
2722 return 0;
2723 }
2724
2725 /* peer-group member updates. */
2726 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002727 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002728 {
2729 if (peer->update_if)
2730 {
2731 if (strcmp (peer->update_if, ifname) == 0)
2732 continue;
2733
2734 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2735 peer->update_if = NULL;
2736 }
2737
2738 if (peer->update_source)
2739 {
2740 sockunion_free (peer->update_source);
2741 peer->update_source = NULL;
2742 }
2743
2744 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2745
2746 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002747 {
2748 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2749 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2750 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2751 }
paul718e3742002-12-13 20:15:29 +00002752 else
2753 BGP_EVENT_ADD (peer, BGP_Stop);
2754 }
2755 return 0;
2756}
2757
2758int
2759peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2760{
2761 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002762 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002763
2764 if (peer->update_source)
2765 {
2766 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2767 && sockunion_cmp (peer->update_source, su) == 0)
2768 return 0;
2769 sockunion_free (peer->update_source);
2770 peer->update_source = NULL;
2771 }
2772
2773 if (peer->update_if)
2774 {
2775 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2776 peer->update_if = NULL;
2777 }
2778
2779 peer->update_source = sockunion_dup (su);
2780
2781 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2782 {
2783 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002784 {
2785 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2786 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2787 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2788 }
paul718e3742002-12-13 20:15:29 +00002789 else
2790 BGP_EVENT_ADD (peer, BGP_Stop);
2791 return 0;
2792 }
2793
2794 /* peer-group member updates. */
2795 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002796 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002797 {
2798 if (peer->update_source)
2799 {
2800 if (sockunion_cmp (peer->update_source, su) == 0)
2801 continue;
2802 sockunion_free (peer->update_source);
2803 peer->update_source = NULL;
2804 }
2805
2806 if (peer->update_if)
2807 {
2808 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2809 peer->update_if = NULL;
2810 }
2811
2812 peer->update_source = sockunion_dup (su);
2813
2814 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002815 {
2816 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2817 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2818 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2819 }
paul718e3742002-12-13 20:15:29 +00002820 else
2821 BGP_EVENT_ADD (peer, BGP_Stop);
2822 }
2823 return 0;
2824}
2825
2826int
2827peer_update_source_unset (struct peer *peer)
2828{
2829 union sockunion *su;
2830 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002831 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002832
2833 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2834 && ! peer->update_source
2835 && ! peer->update_if)
2836 return 0;
2837
2838 if (peer->update_source)
2839 {
2840 sockunion_free (peer->update_source);
2841 peer->update_source = NULL;
2842 }
2843 if (peer->update_if)
2844 {
2845 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2846 peer->update_if = NULL;
2847 }
2848
2849 if (peer_group_active (peer))
2850 {
2851 group = peer->group;
2852
2853 if (group->conf->update_source)
2854 {
2855 su = sockunion_dup (group->conf->update_source);
2856 peer->update_source = su;
2857 }
2858 else if (group->conf->update_if)
2859 peer->update_if =
2860 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2861 }
2862
2863 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2864 {
2865 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002866 {
2867 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2868 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2869 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2870 }
paul718e3742002-12-13 20:15:29 +00002871 else
2872 BGP_EVENT_ADD (peer, BGP_Stop);
2873 return 0;
2874 }
2875
2876 /* peer-group member updates. */
2877 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002878 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002879 {
2880 if (! peer->update_source && ! peer->update_if)
2881 continue;
2882
2883 if (peer->update_source)
2884 {
2885 sockunion_free (peer->update_source);
2886 peer->update_source = NULL;
2887 }
2888
2889 if (peer->update_if)
2890 {
2891 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2892 peer->update_if = NULL;
2893 }
2894
2895 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002896 {
2897 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2898 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2899 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2900 }
paul718e3742002-12-13 20:15:29 +00002901 else
2902 BGP_EVENT_ADD (peer, BGP_Stop);
2903 }
2904 return 0;
2905}
2906
2907int
2908peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002909 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002910{
2911 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002912 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002913
2914 /* Adress family must be activated. */
2915 if (! peer->afc[afi][safi])
2916 return BGP_ERR_PEER_INACTIVE;
2917
2918 /* Default originate can't be used for peer group memeber. */
2919 if (peer_is_group_member (peer, afi, safi))
2920 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2921
2922 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2923 || (rmap && ! peer->default_rmap[afi][safi].name)
2924 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2925 {
2926 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2927
2928 if (rmap)
2929 {
2930 if (peer->default_rmap[afi][safi].name)
2931 free (peer->default_rmap[afi][safi].name);
2932 peer->default_rmap[afi][safi].name = strdup (rmap);
2933 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2934 }
2935 }
2936
2937 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2938 {
2939 if (peer->status == Established && peer->afc_nego[afi][safi])
2940 bgp_default_originate (peer, afi, safi, 0);
2941 return 0;
2942 }
2943
2944 /* peer-group member updates. */
2945 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002946 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002947 {
2948 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2949
2950 if (rmap)
2951 {
2952 if (peer->default_rmap[afi][safi].name)
2953 free (peer->default_rmap[afi][safi].name);
2954 peer->default_rmap[afi][safi].name = strdup (rmap);
2955 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2956 }
2957
2958 if (peer->status == Established && peer->afc_nego[afi][safi])
2959 bgp_default_originate (peer, afi, safi, 0);
2960 }
2961 return 0;
2962}
2963
2964int
2965peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2966{
2967 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002968 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002969
2970 /* Adress family must be activated. */
2971 if (! peer->afc[afi][safi])
2972 return BGP_ERR_PEER_INACTIVE;
2973
2974 /* Default originate can't be used for peer group memeber. */
2975 if (peer_is_group_member (peer, afi, safi))
2976 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2977
2978 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2979 {
2980 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2981
2982 if (peer->default_rmap[afi][safi].name)
2983 free (peer->default_rmap[afi][safi].name);
2984 peer->default_rmap[afi][safi].name = NULL;
2985 peer->default_rmap[afi][safi].map = NULL;
2986 }
2987
2988 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2989 {
2990 if (peer->status == Established && peer->afc_nego[afi][safi])
2991 bgp_default_originate (peer, afi, safi, 1);
2992 return 0;
2993 }
2994
2995 /* peer-group member updates. */
2996 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002997 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002998 {
2999 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3000
3001 if (peer->default_rmap[afi][safi].name)
3002 free (peer->default_rmap[afi][safi].name);
3003 peer->default_rmap[afi][safi].name = NULL;
3004 peer->default_rmap[afi][safi].map = NULL;
3005
3006 if (peer->status == Established && peer->afc_nego[afi][safi])
3007 bgp_default_originate (peer, afi, safi, 1);
3008 }
3009 return 0;
3010}
3011
3012int
3013peer_port_set (struct peer *peer, u_int16_t port)
3014{
3015 peer->port = port;
3016 return 0;
3017}
3018
3019int
3020peer_port_unset (struct peer *peer)
3021{
3022 peer->port = BGP_PORT_DEFAULT;
3023 return 0;
3024}
3025
3026/* neighbor weight. */
3027int
3028peer_weight_set (struct peer *peer, u_int16_t weight)
3029{
3030 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003031 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003032
3033 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3034 peer->weight = weight;
3035
3036 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3037 return 0;
3038
3039 /* peer-group member updates. */
3040 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003041 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003042 {
3043 peer->weight = group->conf->weight;
3044 }
3045 return 0;
3046}
3047
3048int
3049peer_weight_unset (struct peer *peer)
3050{
3051 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003052 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003053
3054 /* Set default weight. */
3055 if (peer_group_active (peer))
3056 peer->weight = peer->group->conf->weight;
3057 else
3058 peer->weight = 0;
3059
3060 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3061
3062 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3063 return 0;
3064
3065 /* peer-group member updates. */
3066 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003067 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003068 {
3069 peer->weight = 0;
3070 }
3071 return 0;
3072}
3073
3074int
3075peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3076{
3077 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003078 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003079
3080 /* Not for peer group memeber. */
3081 if (peer_group_active (peer))
3082 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3083
3084 /* keepalive value check. */
3085 if (keepalive > 65535)
3086 return BGP_ERR_INVALID_VALUE;
3087
3088 /* Holdtime value check. */
3089 if (holdtime > 65535)
3090 return BGP_ERR_INVALID_VALUE;
3091
3092 /* Holdtime value must be either 0 or greater than 3. */
3093 if (holdtime < 3 && holdtime != 0)
3094 return BGP_ERR_INVALID_VALUE;
3095
3096 /* Set value to the configuration. */
3097 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3098 peer->holdtime = holdtime;
3099 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3100
3101 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3102 return 0;
3103
3104 /* peer-group member updates. */
3105 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003106 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003107 {
3108 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3109 peer->holdtime = group->conf->holdtime;
3110 peer->keepalive = group->conf->keepalive;
3111 }
3112 return 0;
3113}
3114
3115int
3116peer_timers_unset (struct peer *peer)
3117{
3118 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003119 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003120
3121 if (peer_group_active (peer))
3122 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3123
3124 /* Clear configuration. */
3125 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3126 peer->keepalive = 0;
3127 peer->holdtime = 0;
3128
3129 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3130 return 0;
3131
3132 /* peer-group member updates. */
3133 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003134 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003135 {
3136 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3137 peer->holdtime = 0;
3138 peer->keepalive = 0;
3139 }
3140
3141 return 0;
3142}
3143
3144int
3145peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3146{
3147 if (peer_group_active (peer))
3148 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3149
3150 if (connect > 65535)
3151 return BGP_ERR_INVALID_VALUE;
3152
3153 /* Set value to the configuration. */
3154 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3155 peer->connect = connect;
3156
3157 /* Set value to timer setting. */
3158 peer->v_connect = connect;
3159
3160 return 0;
3161}
3162
3163int
3164peer_timers_connect_unset (struct peer *peer)
3165{
3166 if (peer_group_active (peer))
3167 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3168
3169 /* Clear configuration. */
3170 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3171 peer->connect = 0;
3172
3173 /* Set timer setting to default value. */
3174 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3175
3176 return 0;
3177}
3178
3179int
3180peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3181{
3182 if (peer_group_active (peer))
3183 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3184
3185 if (routeadv > 600)
3186 return BGP_ERR_INVALID_VALUE;
3187
3188 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3189 peer->routeadv = routeadv;
3190 peer->v_routeadv = routeadv;
3191
3192 return 0;
3193}
3194
3195int
3196peer_advertise_interval_unset (struct peer *peer)
3197{
3198 if (peer_group_active (peer))
3199 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3200
3201 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3202 peer->routeadv = 0;
3203
3204 if (peer_sort (peer) == BGP_PEER_IBGP)
3205 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3206 else
3207 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3208
3209 return 0;
3210}
3211
paul718e3742002-12-13 20:15:29 +00003212/* neighbor interface */
3213int
paulfd79ac92004-10-13 05:06:08 +00003214peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003215{
3216 if (peer->ifname)
3217 free (peer->ifname);
3218 peer->ifname = strdup (str);
3219
3220 return 0;
3221}
3222
3223int
3224peer_interface_unset (struct peer *peer)
3225{
3226 if (peer->ifname)
3227 free (peer->ifname);
3228 peer->ifname = NULL;
3229
3230 return 0;
3231}
3232
3233/* Allow-as in. */
3234int
3235peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3236{
3237 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003238 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003239
3240 if (allow_num < 1 || allow_num > 10)
3241 return BGP_ERR_INVALID_VALUE;
3242
3243 if (peer->allowas_in[afi][safi] != allow_num)
3244 {
3245 peer->allowas_in[afi][safi] = allow_num;
3246 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3247 peer_change_action (peer, afi, safi, peer_change_reset_in);
3248 }
3249
3250 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3251 return 0;
3252
3253 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003254 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003255 {
3256 if (peer->allowas_in[afi][safi] != allow_num)
3257 {
3258 peer->allowas_in[afi][safi] = allow_num;
3259 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3260 peer_change_action (peer, afi, safi, peer_change_reset_in);
3261 }
3262
3263 }
3264 return 0;
3265}
3266
3267int
3268peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3269{
3270 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003271 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003272
3273 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3274 {
3275 peer->allowas_in[afi][safi] = 0;
3276 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3277 }
3278
3279 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3280 return 0;
3281
3282 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003283 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003284 {
3285 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3286 {
3287 peer->allowas_in[afi][safi] = 0;
3288 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3289 }
3290 }
3291 return 0;
3292}
3293
3294int
3295peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3296{
3297 struct bgp *bgp = peer->bgp;
3298 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003299 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003300
3301 if (peer_sort (peer) != BGP_PEER_EBGP
3302 && peer_sort (peer) != BGP_PEER_INTERNAL)
3303 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3304
3305 if (bgp->as == as)
3306 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3307
3308 if (peer_group_active (peer))
3309 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3310
3311 if (peer->change_local_as == as &&
3312 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3313 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3314 return 0;
3315
3316 peer->change_local_as = as;
3317 if (no_prepend)
3318 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3319 else
3320 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3321
3322 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3323 {
3324 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003325 {
3326 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3327 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3328 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3329 }
paul718e3742002-12-13 20:15:29 +00003330 else
3331 BGP_EVENT_ADD (peer, BGP_Stop);
3332
3333 return 0;
3334 }
3335
3336 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003337 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003338 {
3339 peer->change_local_as = as;
3340 if (no_prepend)
3341 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3342 else
3343 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3344
3345 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003346 {
3347 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3348 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3349 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3350 }
paul718e3742002-12-13 20:15:29 +00003351 else
3352 BGP_EVENT_ADD (peer, BGP_Stop);
3353 }
3354
3355 return 0;
3356}
3357
3358int
3359peer_local_as_unset (struct peer *peer)
3360{
3361 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003362 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003363
3364 if (peer_group_active (peer))
3365 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3366
3367 if (! peer->change_local_as)
3368 return 0;
3369
3370 peer->change_local_as = 0;
3371 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3372
3373 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3374 {
3375 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003376 {
3377 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3378 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3379 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3380 }
paul718e3742002-12-13 20:15:29 +00003381 else
3382 BGP_EVENT_ADD (peer, BGP_Stop);
3383
3384 return 0;
3385 }
3386
3387 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003388 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003389 {
3390 peer->change_local_as = 0;
3391 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3392
3393 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003394 {
3395 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3396 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3397 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3398 }
paul718e3742002-12-13 20:15:29 +00003399 else
3400 BGP_EVENT_ADD (peer, BGP_Stop);
3401 }
3402 return 0;
3403}
3404
Paul Jakma0df7c912008-07-21 21:02:49 +00003405/* Set password for authenticating with the peer. */
3406int
3407peer_password_set (struct peer *peer, const char *password)
3408{
3409 struct listnode *nn, *nnode;
3410 int len = password ? strlen(password) : 0;
3411 int ret = BGP_SUCCESS;
3412
3413 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3414 return BGP_ERR_INVALID_VALUE;
3415
3416 if (peer->password && strcmp (peer->password, password) == 0
3417 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3418 return 0;
3419
3420 if (peer->password)
3421 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3422
3423 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3424
3425 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3426 {
3427 if (peer->status == Established)
3428 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3429 else
3430 BGP_EVENT_ADD (peer, BGP_Stop);
3431
3432 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3433 }
3434
3435 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3436 {
3437 if (peer->password && strcmp (peer->password, password) == 0)
3438 continue;
3439
3440 if (peer->password)
3441 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3442
3443 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3444
3445 if (peer->status == Established)
3446 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3447 else
3448 BGP_EVENT_ADD (peer, BGP_Stop);
3449
3450 if (bgp_md5_set (peer) < 0)
3451 ret = BGP_ERR_TCPSIG_FAILED;
3452 }
3453
3454 return ret;
3455}
3456
3457int
3458peer_password_unset (struct peer *peer)
3459{
3460 struct listnode *nn, *nnode;
3461
3462 if (!peer->password
3463 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3464 return 0;
3465
3466 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3467 {
3468 if (peer_group_active (peer)
3469 && peer->group->conf->password
3470 && strcmp (peer->group->conf->password, peer->password) == 0)
3471 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3472
3473 if (peer->status == Established)
3474 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3475 else
3476 BGP_EVENT_ADD (peer, BGP_Stop);
3477
3478 if (peer->password)
3479 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3480
3481 peer->password = NULL;
3482
3483 bgp_md5_set (peer);
3484
3485 return 0;
3486 }
3487
3488 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3489 peer->password = NULL;
3490
3491 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3492 {
3493 if (!peer->password)
3494 continue;
3495
3496 if (peer->status == Established)
3497 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3498 else
3499 BGP_EVENT_ADD (peer, BGP_Stop);
3500
3501 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3502 peer->password = NULL;
3503
3504 bgp_md5_set (peer);
3505 }
3506
3507 return 0;
3508}
3509
paul718e3742002-12-13 20:15:29 +00003510/* Set distribute list to the peer. */
3511int
3512peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003513 const char *name)
paul718e3742002-12-13 20:15:29 +00003514{
3515 struct bgp_filter *filter;
3516 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003517 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003518
3519 if (! peer->afc[afi][safi])
3520 return BGP_ERR_PEER_INACTIVE;
3521
3522 if (direct != FILTER_IN && direct != FILTER_OUT)
3523 return BGP_ERR_INVALID_VALUE;
3524
3525 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3526 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3527
3528 filter = &peer->filter[afi][safi];
3529
3530 if (filter->plist[direct].name)
3531 return BGP_ERR_PEER_FILTER_CONFLICT;
3532
3533 if (filter->dlist[direct].name)
3534 free (filter->dlist[direct].name);
3535 filter->dlist[direct].name = strdup (name);
3536 filter->dlist[direct].alist = access_list_lookup (afi, name);
3537
3538 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3539 return 0;
3540
3541 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003542 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003543 {
3544 filter = &peer->filter[afi][safi];
3545
3546 if (! peer->af_group[afi][safi])
3547 continue;
3548
3549 if (filter->dlist[direct].name)
3550 free (filter->dlist[direct].name);
3551 filter->dlist[direct].name = strdup (name);
3552 filter->dlist[direct].alist = access_list_lookup (afi, name);
3553 }
3554
3555 return 0;
3556}
3557
3558int
3559peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3560{
3561 struct bgp_filter *filter;
3562 struct bgp_filter *gfilter;
3563 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003564 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003565
3566 if (! peer->afc[afi][safi])
3567 return BGP_ERR_PEER_INACTIVE;
3568
3569 if (direct != FILTER_IN && direct != FILTER_OUT)
3570 return BGP_ERR_INVALID_VALUE;
3571
3572 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3573 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3574
3575 filter = &peer->filter[afi][safi];
3576
3577 /* apply peer-group filter */
3578 if (peer->af_group[afi][safi])
3579 {
3580 gfilter = &peer->group->conf->filter[afi][safi];
3581
3582 if (gfilter->dlist[direct].name)
3583 {
3584 if (filter->dlist[direct].name)
3585 free (filter->dlist[direct].name);
3586 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3587 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3588 return 0;
3589 }
3590 }
3591
3592 if (filter->dlist[direct].name)
3593 free (filter->dlist[direct].name);
3594 filter->dlist[direct].name = NULL;
3595 filter->dlist[direct].alist = NULL;
3596
3597 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3598 return 0;
3599
3600 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003601 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003602 {
3603 filter = &peer->filter[afi][safi];
3604
3605 if (! peer->af_group[afi][safi])
3606 continue;
3607
3608 if (filter->dlist[direct].name)
3609 free (filter->dlist[direct].name);
3610 filter->dlist[direct].name = NULL;
3611 filter->dlist[direct].alist = NULL;
3612 }
3613
3614 return 0;
3615}
3616
3617/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003618static void
paul718e3742002-12-13 20:15:29 +00003619peer_distribute_update (struct access_list *access)
3620{
3621 afi_t afi;
3622 safi_t safi;
3623 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003624 struct listnode *mnode, *mnnode;
3625 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003626 struct bgp *bgp;
3627 struct peer *peer;
3628 struct peer_group *group;
3629 struct bgp_filter *filter;
3630
paul1eb8ef22005-04-07 07:30:20 +00003631 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003632 {
paul1eb8ef22005-04-07 07:30:20 +00003633 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003634 {
3635 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3636 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3637 {
3638 filter = &peer->filter[afi][safi];
3639
3640 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3641 {
3642 if (filter->dlist[direct].name)
3643 filter->dlist[direct].alist =
3644 access_list_lookup (afi, filter->dlist[direct].name);
3645 else
3646 filter->dlist[direct].alist = NULL;
3647 }
3648 }
3649 }
paul1eb8ef22005-04-07 07:30:20 +00003650 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003651 {
3652 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3653 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3654 {
3655 filter = &group->conf->filter[afi][safi];
3656
3657 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3658 {
3659 if (filter->dlist[direct].name)
3660 filter->dlist[direct].alist =
3661 access_list_lookup (afi, filter->dlist[direct].name);
3662 else
3663 filter->dlist[direct].alist = NULL;
3664 }
3665 }
3666 }
3667 }
3668}
3669
3670/* Set prefix list to the peer. */
3671int
3672peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003673 const char *name)
paul718e3742002-12-13 20:15:29 +00003674{
3675 struct bgp_filter *filter;
3676 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003677 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003678
3679 if (! peer->afc[afi][safi])
3680 return BGP_ERR_PEER_INACTIVE;
3681
3682 if (direct != FILTER_IN && direct != FILTER_OUT)
3683 return BGP_ERR_INVALID_VALUE;
3684
3685 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3686 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3687
3688 filter = &peer->filter[afi][safi];
3689
3690 if (filter->dlist[direct].name)
3691 return BGP_ERR_PEER_FILTER_CONFLICT;
3692
3693 if (filter->plist[direct].name)
3694 free (filter->plist[direct].name);
3695 filter->plist[direct].name = strdup (name);
3696 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3697
3698 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3699 return 0;
3700
3701 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003702 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003703 {
3704 filter = &peer->filter[afi][safi];
3705
3706 if (! peer->af_group[afi][safi])
3707 continue;
3708
3709 if (filter->plist[direct].name)
3710 free (filter->plist[direct].name);
3711 filter->plist[direct].name = strdup (name);
3712 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3713 }
3714 return 0;
3715}
3716
3717int
3718peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3719{
3720 struct bgp_filter *filter;
3721 struct bgp_filter *gfilter;
3722 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003723 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003724
3725 if (! peer->afc[afi][safi])
3726 return BGP_ERR_PEER_INACTIVE;
3727
3728 if (direct != FILTER_IN && direct != FILTER_OUT)
3729 return BGP_ERR_INVALID_VALUE;
3730
3731 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3732 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3733
3734 filter = &peer->filter[afi][safi];
3735
3736 /* apply peer-group filter */
3737 if (peer->af_group[afi][safi])
3738 {
3739 gfilter = &peer->group->conf->filter[afi][safi];
3740
3741 if (gfilter->plist[direct].name)
3742 {
3743 if (filter->plist[direct].name)
3744 free (filter->plist[direct].name);
3745 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3746 filter->plist[direct].plist = gfilter->plist[direct].plist;
3747 return 0;
3748 }
3749 }
3750
3751 if (filter->plist[direct].name)
3752 free (filter->plist[direct].name);
3753 filter->plist[direct].name = NULL;
3754 filter->plist[direct].plist = NULL;
3755
3756 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3757 return 0;
3758
3759 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003760 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003761 {
3762 filter = &peer->filter[afi][safi];
3763
3764 if (! peer->af_group[afi][safi])
3765 continue;
3766
3767 if (filter->plist[direct].name)
3768 free (filter->plist[direct].name);
3769 filter->plist[direct].name = NULL;
3770 filter->plist[direct].plist = NULL;
3771 }
3772
3773 return 0;
3774}
3775
3776/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003777static void
paul718e3742002-12-13 20:15:29 +00003778peer_prefix_list_update (struct prefix_list *plist)
3779{
paul1eb8ef22005-04-07 07:30:20 +00003780 struct listnode *mnode, *mnnode;
3781 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003782 struct bgp *bgp;
3783 struct peer *peer;
3784 struct peer_group *group;
3785 struct bgp_filter *filter;
3786 afi_t afi;
3787 safi_t safi;
3788 int direct;
3789
paul1eb8ef22005-04-07 07:30:20 +00003790 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003791 {
paul1eb8ef22005-04-07 07:30:20 +00003792 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003793 {
3794 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3795 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3796 {
3797 filter = &peer->filter[afi][safi];
3798
3799 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3800 {
3801 if (filter->plist[direct].name)
3802 filter->plist[direct].plist =
3803 prefix_list_lookup (afi, filter->plist[direct].name);
3804 else
3805 filter->plist[direct].plist = NULL;
3806 }
3807 }
3808 }
paul1eb8ef22005-04-07 07:30:20 +00003809 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003810 {
3811 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3812 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3813 {
3814 filter = &group->conf->filter[afi][safi];
3815
3816 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3817 {
3818 if (filter->plist[direct].name)
3819 filter->plist[direct].plist =
3820 prefix_list_lookup (afi, filter->plist[direct].name);
3821 else
3822 filter->plist[direct].plist = NULL;
3823 }
3824 }
3825 }
3826 }
3827}
3828
3829int
3830peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003831 const char *name)
paul718e3742002-12-13 20:15:29 +00003832{
3833 struct bgp_filter *filter;
3834 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003835 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003836
3837 if (! peer->afc[afi][safi])
3838 return BGP_ERR_PEER_INACTIVE;
3839
3840 if (direct != FILTER_IN && direct != FILTER_OUT)
3841 return BGP_ERR_INVALID_VALUE;
3842
3843 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3844 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3845
3846 filter = &peer->filter[afi][safi];
3847
3848 if (filter->aslist[direct].name)
3849 free (filter->aslist[direct].name);
3850 filter->aslist[direct].name = strdup (name);
3851 filter->aslist[direct].aslist = as_list_lookup (name);
3852
3853 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3854 return 0;
3855
3856 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003857 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003858 {
3859 filter = &peer->filter[afi][safi];
3860
3861 if (! peer->af_group[afi][safi])
3862 continue;
3863
3864 if (filter->aslist[direct].name)
3865 free (filter->aslist[direct].name);
3866 filter->aslist[direct].name = strdup (name);
3867 filter->aslist[direct].aslist = as_list_lookup (name);
3868 }
3869 return 0;
3870}
3871
3872int
3873peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3874{
3875 struct bgp_filter *filter;
3876 struct bgp_filter *gfilter;
3877 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003878 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003879
3880 if (! peer->afc[afi][safi])
3881 return BGP_ERR_PEER_INACTIVE;
3882
hassob5f29602005-05-25 21:00:28 +00003883 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003884 return BGP_ERR_INVALID_VALUE;
3885
hassob5f29602005-05-25 21:00:28 +00003886 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003887 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3888
3889 filter = &peer->filter[afi][safi];
3890
3891 /* apply peer-group filter */
3892 if (peer->af_group[afi][safi])
3893 {
3894 gfilter = &peer->group->conf->filter[afi][safi];
3895
3896 if (gfilter->aslist[direct].name)
3897 {
3898 if (filter->aslist[direct].name)
3899 free (filter->aslist[direct].name);
3900 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3901 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3902 return 0;
3903 }
3904 }
3905
3906 if (filter->aslist[direct].name)
3907 free (filter->aslist[direct].name);
3908 filter->aslist[direct].name = NULL;
3909 filter->aslist[direct].aslist = NULL;
3910
3911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3912 return 0;
3913
3914 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003915 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003916 {
3917 filter = &peer->filter[afi][safi];
3918
3919 if (! peer->af_group[afi][safi])
3920 continue;
3921
3922 if (filter->aslist[direct].name)
3923 free (filter->aslist[direct].name);
3924 filter->aslist[direct].name = NULL;
3925 filter->aslist[direct].aslist = NULL;
3926 }
3927
3928 return 0;
3929}
3930
paul94f2b392005-06-28 12:44:16 +00003931static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003932peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003933{
3934 afi_t afi;
3935 safi_t safi;
3936 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003937 struct listnode *mnode, *mnnode;
3938 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003939 struct bgp *bgp;
3940 struct peer *peer;
3941 struct peer_group *group;
3942 struct bgp_filter *filter;
3943
paul1eb8ef22005-04-07 07:30:20 +00003944 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003945 {
paul1eb8ef22005-04-07 07:30:20 +00003946 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003947 {
3948 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3949 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3950 {
3951 filter = &peer->filter[afi][safi];
3952
3953 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3954 {
3955 if (filter->aslist[direct].name)
3956 filter->aslist[direct].aslist =
3957 as_list_lookup (filter->aslist[direct].name);
3958 else
3959 filter->aslist[direct].aslist = NULL;
3960 }
3961 }
3962 }
paul1eb8ef22005-04-07 07:30:20 +00003963 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003964 {
3965 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3966 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3967 {
3968 filter = &group->conf->filter[afi][safi];
3969
3970 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3971 {
3972 if (filter->aslist[direct].name)
3973 filter->aslist[direct].aslist =
3974 as_list_lookup (filter->aslist[direct].name);
3975 else
3976 filter->aslist[direct].aslist = NULL;
3977 }
3978 }
3979 }
3980 }
3981}
3982
3983/* Set route-map to the peer. */
3984int
3985peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003986 const char *name)
paul718e3742002-12-13 20:15:29 +00003987{
3988 struct bgp_filter *filter;
3989 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003990 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003991
3992 if (! peer->afc[afi][safi])
3993 return BGP_ERR_PEER_INACTIVE;
3994
paulfee0f4c2004-09-13 05:12:46 +00003995 if (direct != RMAP_IN && direct != RMAP_OUT &&
3996 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003997 return BGP_ERR_INVALID_VALUE;
3998
paulfee0f4c2004-09-13 05:12:46 +00003999 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4000 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004001 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4002
4003 filter = &peer->filter[afi][safi];
4004
4005 if (filter->map[direct].name)
4006 free (filter->map[direct].name);
4007
4008 filter->map[direct].name = strdup (name);
4009 filter->map[direct].map = route_map_lookup_by_name (name);
4010
4011 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4012 return 0;
4013
4014 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004015 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004016 {
4017 filter = &peer->filter[afi][safi];
4018
4019 if (! peer->af_group[afi][safi])
4020 continue;
4021
4022 if (filter->map[direct].name)
4023 free (filter->map[direct].name);
4024 filter->map[direct].name = strdup (name);
4025 filter->map[direct].map = route_map_lookup_by_name (name);
4026 }
4027 return 0;
4028}
4029
4030/* Unset route-map from the peer. */
4031int
4032peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4033{
4034 struct bgp_filter *filter;
4035 struct bgp_filter *gfilter;
4036 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004037 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004038
4039 if (! peer->afc[afi][safi])
4040 return BGP_ERR_PEER_INACTIVE;
4041
hassob5f29602005-05-25 21:00:28 +00004042 if (direct != RMAP_IN && direct != RMAP_OUT &&
4043 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004044 return BGP_ERR_INVALID_VALUE;
4045
hassob5f29602005-05-25 21:00:28 +00004046 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4047 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004048 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4049
4050 filter = &peer->filter[afi][safi];
4051
4052 /* apply peer-group filter */
4053 if (peer->af_group[afi][safi])
4054 {
4055 gfilter = &peer->group->conf->filter[afi][safi];
4056
4057 if (gfilter->map[direct].name)
4058 {
4059 if (filter->map[direct].name)
4060 free (filter->map[direct].name);
4061 filter->map[direct].name = strdup (gfilter->map[direct].name);
4062 filter->map[direct].map = gfilter->map[direct].map;
4063 return 0;
4064 }
4065 }
4066
4067 if (filter->map[direct].name)
4068 free (filter->map[direct].name);
4069 filter->map[direct].name = NULL;
4070 filter->map[direct].map = NULL;
4071
4072 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4073 return 0;
4074
4075 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004076 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004077 {
4078 filter = &peer->filter[afi][safi];
4079
4080 if (! peer->af_group[afi][safi])
4081 continue;
4082
4083 if (filter->map[direct].name)
4084 free (filter->map[direct].name);
4085 filter->map[direct].name = NULL;
4086 filter->map[direct].map = NULL;
4087 }
4088 return 0;
4089}
4090
4091/* Set unsuppress-map to the peer. */
4092int
paulfd79ac92004-10-13 05:06:08 +00004093peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4094 const char *name)
paul718e3742002-12-13 20:15:29 +00004095{
4096 struct bgp_filter *filter;
4097 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004098 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004099
4100 if (! peer->afc[afi][safi])
4101 return BGP_ERR_PEER_INACTIVE;
4102
4103 if (peer_is_group_member (peer, afi, safi))
4104 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4105
4106 filter = &peer->filter[afi][safi];
4107
4108 if (filter->usmap.name)
4109 free (filter->usmap.name);
4110
4111 filter->usmap.name = strdup (name);
4112 filter->usmap.map = route_map_lookup_by_name (name);
4113
4114 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4115 return 0;
4116
4117 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004118 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004119 {
4120 filter = &peer->filter[afi][safi];
4121
4122 if (! peer->af_group[afi][safi])
4123 continue;
4124
4125 if (filter->usmap.name)
4126 free (filter->usmap.name);
4127 filter->usmap.name = strdup (name);
4128 filter->usmap.map = route_map_lookup_by_name (name);
4129 }
4130 return 0;
4131}
4132
4133/* Unset route-map from the peer. */
4134int
4135peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4136{
4137 struct bgp_filter *filter;
4138 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004139 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004140
4141 if (! peer->afc[afi][safi])
4142 return BGP_ERR_PEER_INACTIVE;
4143
4144 if (peer_is_group_member (peer, afi, safi))
4145 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4146
4147 filter = &peer->filter[afi][safi];
4148
4149 if (filter->usmap.name)
4150 free (filter->usmap.name);
4151 filter->usmap.name = NULL;
4152 filter->usmap.map = NULL;
4153
4154 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4155 return 0;
4156
4157 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004158 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004159 {
4160 filter = &peer->filter[afi][safi];
4161
4162 if (! peer->af_group[afi][safi])
4163 continue;
4164
4165 if (filter->usmap.name)
4166 free (filter->usmap.name);
4167 filter->usmap.name = NULL;
4168 filter->usmap.map = NULL;
4169 }
4170 return 0;
4171}
4172
4173int
4174peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004175 u_int32_t max, u_char threshold,
4176 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004177{
4178 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004179 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004180
4181 if (! peer->afc[afi][safi])
4182 return BGP_ERR_PEER_INACTIVE;
4183
4184 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4185 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004186 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004187 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004188 if (warning)
4189 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4190 else
4191 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4192
4193 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4194 return 0;
4195
4196 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004197 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004198 {
4199 if (! peer->af_group[afi][safi])
4200 continue;
4201
4202 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4203 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004204 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004205 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004206 if (warning)
4207 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4208 else
4209 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4210 }
4211 return 0;
4212}
4213
4214int
4215peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4216{
4217 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004218 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004219
4220 if (! peer->afc[afi][safi])
4221 return BGP_ERR_PEER_INACTIVE;
4222
4223 /* apply peer-group config */
4224 if (peer->af_group[afi][safi])
4225 {
4226 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4227 PEER_FLAG_MAX_PREFIX))
4228 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4229 else
4230 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4231
4232 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4233 PEER_FLAG_MAX_PREFIX_WARNING))
4234 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4235 else
4236 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4237
4238 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004239 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004240 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004241 return 0;
4242 }
4243
4244 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4245 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4246 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004247 peer->pmax_threshold[afi][safi] = 0;
4248 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004249
4250 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4251 return 0;
4252
4253 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004254 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004255 {
4256 if (! peer->af_group[afi][safi])
4257 continue;
4258
4259 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4260 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4261 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004262 peer->pmax_threshold[afi][safi] = 0;
4263 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004264 }
4265 return 0;
4266}
4267
4268int
4269peer_clear (struct peer *peer)
4270{
4271 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4272 {
hasso0a486e52005-02-01 20:57:17 +00004273 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4274 {
4275 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4276 if (peer->t_pmax_restart)
4277 {
4278 BGP_TIMER_OFF (peer->t_pmax_restart);
4279 if (BGP_DEBUG (events, EVENTS))
4280 zlog_debug ("%s Maximum-prefix restart timer canceled",
4281 peer->host);
4282 }
4283 BGP_EVENT_ADD (peer, BGP_Start);
4284 return 0;
4285 }
4286
paul718e3742002-12-13 20:15:29 +00004287 peer->v_start = BGP_INIT_START_TIMER;
4288 if (peer->status == Established)
4289 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4290 BGP_NOTIFY_CEASE_ADMIN_RESET);
4291 else
4292 BGP_EVENT_ADD (peer, BGP_Stop);
4293 }
4294 return 0;
4295}
4296
4297int
4298peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4299 enum bgp_clear_type stype)
4300{
4301 if (peer->status != Established)
4302 return 0;
4303
4304 if (! peer->afc[afi][safi])
4305 return BGP_ERR_AF_UNCONFIGURED;
4306
paulfee0f4c2004-09-13 05:12:46 +00004307 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4308 {
4309 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4310 return 0;
4311 bgp_check_local_routes_rsclient (peer, afi, safi);
4312 bgp_soft_reconfig_rsclient (peer, afi, safi);
4313 }
4314
paul718e3742002-12-13 20:15:29 +00004315 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4316 bgp_announce_route (peer, afi, safi);
4317
4318 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4319 {
4320 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4321 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4322 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4323 {
4324 struct bgp_filter *filter = &peer->filter[afi][safi];
4325 u_char prefix_type;
4326
4327 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4328 prefix_type = ORF_TYPE_PREFIX;
4329 else
4330 prefix_type = ORF_TYPE_PREFIX_OLD;
4331
4332 if (filter->plist[FILTER_IN].plist)
4333 {
4334 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4335 bgp_route_refresh_send (peer, afi, safi,
4336 prefix_type, REFRESH_DEFER, 1);
4337 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4338 REFRESH_IMMEDIATE, 0);
4339 }
4340 else
4341 {
4342 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4343 bgp_route_refresh_send (peer, afi, safi,
4344 prefix_type, REFRESH_IMMEDIATE, 1);
4345 else
4346 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4347 }
4348 return 0;
4349 }
4350 }
4351
4352 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4353 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4354 {
4355 /* If neighbor has soft reconfiguration inbound flag.
4356 Use Adj-RIB-In database. */
4357 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4358 bgp_soft_reconfig_in (peer, afi, safi);
4359 else
4360 {
4361 /* If neighbor has route refresh capability, send route refresh
4362 message to the peer. */
4363 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4364 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4365 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4366 else
4367 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4368 }
4369 }
4370 return 0;
4371}
4372
paulfd79ac92004-10-13 05:06:08 +00004373/* Display peer uptime.*/
4374/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004375char *
4376peer_uptime (time_t uptime2, char *buf, size_t len)
4377{
4378 time_t uptime1;
4379 struct tm *tm;
4380
4381 /* Check buffer length. */
4382 if (len < BGP_UPTIME_LEN)
4383 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004384 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004385 /* XXX: should return status instead of buf... */
4386 snprintf (buf, len, "<error> ");
4387 return buf;
paul718e3742002-12-13 20:15:29 +00004388 }
4389
4390 /* If there is no connection has been done before print `never'. */
4391 if (uptime2 == 0)
4392 {
4393 snprintf (buf, len, "never ");
4394 return buf;
4395 }
4396
4397 /* Get current time. */
4398 uptime1 = time (NULL);
4399 uptime1 -= uptime2;
4400 tm = gmtime (&uptime1);
4401
4402 /* Making formatted timer strings. */
4403#define ONE_DAY_SECOND 60*60*24
4404#define ONE_WEEK_SECOND 60*60*24*7
4405
4406 if (uptime1 < ONE_DAY_SECOND)
4407 snprintf (buf, len, "%02d:%02d:%02d",
4408 tm->tm_hour, tm->tm_min, tm->tm_sec);
4409 else if (uptime1 < ONE_WEEK_SECOND)
4410 snprintf (buf, len, "%dd%02dh%02dm",
4411 tm->tm_yday, tm->tm_hour, tm->tm_min);
4412 else
4413 snprintf (buf, len, "%02dw%dd%02dh",
4414 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4415 return buf;
4416}
4417
paul94f2b392005-06-28 12:44:16 +00004418static void
paul718e3742002-12-13 20:15:29 +00004419bgp_config_write_filter (struct vty *vty, struct peer *peer,
4420 afi_t afi, safi_t safi)
4421{
4422 struct bgp_filter *filter;
4423 struct bgp_filter *gfilter = NULL;
4424 char *addr;
4425 int in = FILTER_IN;
4426 int out = FILTER_OUT;
4427
4428 addr = peer->host;
4429 filter = &peer->filter[afi][safi];
4430 if (peer->af_group[afi][safi])
4431 gfilter = &peer->group->conf->filter[afi][safi];
4432
4433 /* distribute-list. */
4434 if (filter->dlist[in].name)
4435 if (! gfilter || ! gfilter->dlist[in].name
4436 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4437 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4438 filter->dlist[in].name, VTY_NEWLINE);
4439 if (filter->dlist[out].name && ! gfilter)
4440 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4441 filter->dlist[out].name, VTY_NEWLINE);
4442
4443 /* prefix-list. */
4444 if (filter->plist[in].name)
4445 if (! gfilter || ! gfilter->plist[in].name
4446 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4447 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4448 filter->plist[in].name, VTY_NEWLINE);
4449 if (filter->plist[out].name && ! gfilter)
4450 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4451 filter->plist[out].name, VTY_NEWLINE);
4452
4453 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004454 if (filter->map[RMAP_IN].name)
4455 if (! gfilter || ! gfilter->map[RMAP_IN].name
4456 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004457 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004458 filter->map[RMAP_IN].name, VTY_NEWLINE);
4459 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004460 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004461 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4462 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4463 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4464 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4465 if (filter->map[RMAP_EXPORT].name)
4466 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4467 || strcmp (filter->map[RMAP_EXPORT].name,
4468 gfilter->map[RMAP_EXPORT].name) != 0)
4469 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4470 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004471
4472 /* unsuppress-map */
4473 if (filter->usmap.name && ! gfilter)
4474 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4475 filter->usmap.name, VTY_NEWLINE);
4476
4477 /* filter-list. */
4478 if (filter->aslist[in].name)
4479 if (! gfilter || ! gfilter->aslist[in].name
4480 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4481 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4482 filter->aslist[in].name, VTY_NEWLINE);
4483 if (filter->aslist[out].name && ! gfilter)
4484 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4485 filter->aslist[out].name, VTY_NEWLINE);
4486}
4487
4488/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004489static void
paul718e3742002-12-13 20:15:29 +00004490bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4491 struct peer *peer, afi_t afi, safi_t safi)
4492{
4493 struct bgp_filter *filter;
4494 struct peer *g_peer = NULL;
4495 char buf[SU_ADDRSTRLEN];
4496 char *addr;
4497
4498 filter = &peer->filter[afi][safi];
4499 addr = peer->host;
4500 if (peer_group_active (peer))
4501 g_peer = peer->group->conf;
4502
4503 /************************************
4504 ****** Global to the neighbor ******
4505 ************************************/
4506 if (afi == AFI_IP && safi == SAFI_UNICAST)
4507 {
4508 /* remote-as. */
4509 if (! peer_group_active (peer))
4510 {
4511 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4512 vty_out (vty, " neighbor %s peer-group%s", addr,
4513 VTY_NEWLINE);
4514 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004515 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004516 VTY_NEWLINE);
4517 }
4518 else
4519 {
4520 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004521 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004522 VTY_NEWLINE);
4523 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4524 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4525 peer->group->name, VTY_NEWLINE);
4526 }
4527
4528 /* local-as. */
4529 if (peer->change_local_as)
4530 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004531 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004532 peer->change_local_as,
4533 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4534 " no-prepend" : "", VTY_NEWLINE);
4535
4536 /* Description. */
4537 if (peer->desc)
4538 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4539 VTY_NEWLINE);
4540
4541 /* Shutdown. */
4542 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4543 if (! peer_group_active (peer) ||
4544 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4545 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4546
Paul Jakma0df7c912008-07-21 21:02:49 +00004547 /* Password. */
4548 if (peer->password)
4549 if (!peer_group_active (peer)
4550 || ! g_peer->password
4551 || strcmp (peer->password, g_peer->password) != 0)
4552 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4553 VTY_NEWLINE);
4554
paul718e3742002-12-13 20:15:29 +00004555 /* BGP port. */
4556 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004557 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004558 VTY_NEWLINE);
4559
4560 /* Local interface name. */
4561 if (peer->ifname)
4562 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4563 VTY_NEWLINE);
4564
4565 /* Passive. */
4566 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4567 if (! peer_group_active (peer) ||
4568 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4569 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4570
4571 /* EBGP multihop. */
4572 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4573 if (! peer_group_active (peer) ||
4574 g_peer->ttl != peer->ttl)
4575 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4576 VTY_NEWLINE);
4577
hasso6ffd2072005-02-02 14:50:11 +00004578 /* disable-connected-check. */
4579 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004580 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004581 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4582 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004583
4584 /* Update-source. */
4585 if (peer->update_if)
4586 if (! peer_group_active (peer) || ! g_peer->update_if
4587 || strcmp (g_peer->update_if, peer->update_if) != 0)
4588 vty_out (vty, " neighbor %s update-source %s%s", addr,
4589 peer->update_if, VTY_NEWLINE);
4590 if (peer->update_source)
4591 if (! peer_group_active (peer) || ! g_peer->update_source
4592 || sockunion_cmp (g_peer->update_source,
4593 peer->update_source) != 0)
4594 vty_out (vty, " neighbor %s update-source %s%s", addr,
4595 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4596 VTY_NEWLINE);
4597
paul718e3742002-12-13 20:15:29 +00004598 /* advertisement-interval */
4599 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4600 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4601 addr, peer->v_routeadv, VTY_NEWLINE);
4602
4603 /* timers. */
4604 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4605 && ! peer_group_active (peer))
4606 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4607 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4608
4609 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4610 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4611 peer->connect, VTY_NEWLINE);
4612
4613 /* Default weight. */
4614 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4615 if (! peer_group_active (peer) ||
4616 g_peer->weight != peer->weight)
4617 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4618 VTY_NEWLINE);
4619
paul718e3742002-12-13 20:15:29 +00004620 /* Dynamic capability. */
4621 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4622 if (! peer_group_active (peer) ||
4623 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4624 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4625 VTY_NEWLINE);
4626
4627 /* dont capability negotiation. */
4628 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4629 if (! peer_group_active (peer) ||
4630 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4631 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4632 VTY_NEWLINE);
4633
4634 /* override capability negotiation. */
4635 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4636 if (! peer_group_active (peer) ||
4637 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4638 vty_out (vty, " neighbor %s override-capability%s", addr,
4639 VTY_NEWLINE);
4640
4641 /* strict capability negotiation. */
4642 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4643 if (! peer_group_active (peer) ||
4644 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4645 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4646 VTY_NEWLINE);
4647
4648 if (! peer_group_active (peer))
4649 {
4650 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4651 {
4652 if (peer->afc[AFI_IP][SAFI_UNICAST])
4653 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4654 }
4655 else
4656 {
4657 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4658 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4659 }
4660 }
4661 }
4662
4663
4664 /************************************
4665 ****** Per AF to the neighbor ******
4666 ************************************/
4667
4668 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4669 {
4670 if (peer->af_group[afi][safi])
4671 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4672 peer->group->name, VTY_NEWLINE);
4673 else
4674 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4675 }
4676
4677 /* ORF capability. */
4678 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4679 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4680 if (! peer->af_group[afi][safi])
4681 {
4682 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4683
4684 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4685 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4686 vty_out (vty, " both");
4687 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4688 vty_out (vty, " send");
4689 else
4690 vty_out (vty, " receive");
4691 vty_out (vty, "%s", VTY_NEWLINE);
4692 }
4693
4694 /* Route reflector client. */
4695 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4696 && ! peer->af_group[afi][safi])
4697 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4698 VTY_NEWLINE);
4699
4700 /* Nexthop self. */
4701 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4702 && ! peer->af_group[afi][safi])
4703 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4704
4705 /* Remove private AS. */
4706 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4707 && ! peer->af_group[afi][safi])
4708 vty_out (vty, " neighbor %s remove-private-AS%s",
4709 addr, VTY_NEWLINE);
4710
4711 /* send-community print. */
4712 if (! peer->af_group[afi][safi])
4713 {
4714 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4715 {
4716 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4717 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4718 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4719 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4720 vty_out (vty, " neighbor %s send-community extended%s",
4721 addr, VTY_NEWLINE);
4722 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4723 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4724 }
4725 else
4726 {
4727 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4728 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4729 vty_out (vty, " no neighbor %s send-community both%s",
4730 addr, VTY_NEWLINE);
4731 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4732 vty_out (vty, " no neighbor %s send-community extended%s",
4733 addr, VTY_NEWLINE);
4734 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4735 vty_out (vty, " no neighbor %s send-community%s",
4736 addr, VTY_NEWLINE);
4737 }
4738 }
4739
4740 /* Default information */
4741 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4742 && ! peer->af_group[afi][safi])
4743 {
4744 vty_out (vty, " neighbor %s default-originate", addr);
4745 if (peer->default_rmap[afi][safi].name)
4746 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4747 vty_out (vty, "%s", VTY_NEWLINE);
4748 }
4749
4750 /* Soft reconfiguration inbound. */
4751 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4752 if (! peer->af_group[afi][safi] ||
4753 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4754 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4755 VTY_NEWLINE);
4756
4757 /* maximum-prefix. */
4758 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4759 if (! peer->af_group[afi][safi]
4760 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004761 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004762 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4763 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004764 {
hasso0a486e52005-02-01 20:57:17 +00004765 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4766 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4767 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4768 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4769 vty_out (vty, " warning-only");
4770 if (peer->pmax_restart[afi][safi])
4771 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4772 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004773 }
paul718e3742002-12-13 20:15:29 +00004774
4775 /* Route server client. */
4776 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4777 && ! peer->af_group[afi][safi])
4778 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4779
4780 /* Allow AS in. */
4781 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4782 if (! peer_group_active (peer)
4783 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4784 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4785 {
4786 if (peer->allowas_in[afi][safi] == 3)
4787 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4788 else
4789 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4790 peer->allowas_in[afi][safi], VTY_NEWLINE);
4791 }
4792
4793 /* Filter. */
4794 bgp_config_write_filter (vty, peer, afi, safi);
4795
4796 /* atribute-unchanged. */
4797 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4798 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4799 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4800 && ! peer->af_group[afi][safi])
4801 {
4802 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4803 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4804 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4805 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4806 else
4807 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4808 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4809 " as-path" : "",
4810 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4811 " next-hop" : "",
4812 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4813 " med" : "", VTY_NEWLINE);
4814 }
4815}
4816
4817/* Display "address-family" configuration header. */
4818void
4819bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4820 int *write)
4821{
4822 if (*write)
4823 return;
4824
4825 if (afi == AFI_IP && safi == SAFI_UNICAST)
4826 return;
4827
4828 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4829
4830 if (afi == AFI_IP)
4831 {
4832 if (safi == SAFI_MULTICAST)
4833 vty_out (vty, "ipv4 multicast");
4834 else if (safi == SAFI_MPLS_VPN)
4835 vty_out (vty, "vpnv4 unicast");
4836 }
4837 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004838 {
4839 vty_out (vty, "ipv6");
4840
4841 if (safi == SAFI_MULTICAST)
4842 vty_out (vty, " multicast");
4843 }
paul718e3742002-12-13 20:15:29 +00004844
4845 vty_out (vty, "%s", VTY_NEWLINE);
4846
4847 *write = 1;
4848}
4849
4850/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004851static int
paul718e3742002-12-13 20:15:29 +00004852bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4853 safi_t safi)
4854{
4855 int write = 0;
4856 struct peer *peer;
4857 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004858 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004859
4860 bgp_config_write_network (vty, bgp, afi, safi, &write);
4861
4862 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4863
paul1eb8ef22005-04-07 07:30:20 +00004864 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004865 {
4866 if (group->conf->afc[afi][safi])
4867 {
4868 bgp_config_write_family_header (vty, afi, safi, &write);
4869 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4870 }
4871 }
paul1eb8ef22005-04-07 07:30:20 +00004872 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004873 {
4874 if (peer->afc[afi][safi])
4875 {
4876 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4877 {
4878 bgp_config_write_family_header (vty, afi, safi, &write);
4879 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4880 }
4881 }
4882 }
4883 if (write)
4884 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4885
4886 return write;
4887}
4888
4889int
4890bgp_config_write (struct vty *vty)
4891{
4892 int write = 0;
4893 struct bgp *bgp;
4894 struct peer_group *group;
4895 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004896 struct listnode *node, *nnode;
4897 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004898
4899 /* BGP Multiple instance. */
4900 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4901 {
4902 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4903 write++;
4904 }
4905
4906 /* BGP Config type. */
4907 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4908 {
4909 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4910 write++;
4911 }
4912
4913 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004914 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004915 {
4916 if (write)
4917 vty_out (vty, "!%s", VTY_NEWLINE);
4918
4919 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004920 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004921
4922 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4923 {
4924 if (bgp->name)
4925 vty_out (vty, " view %s", bgp->name);
4926 }
4927 vty_out (vty, "%s", VTY_NEWLINE);
4928
4929 /* No Synchronization */
4930 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4931 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4932
4933 /* BGP fast-external-failover. */
4934 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4935 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4936
4937 /* BGP router ID. */
4938 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4939 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4940 VTY_NEWLINE);
4941
paul848973c2003-08-13 00:32:49 +00004942 /* BGP log-neighbor-changes. */
4943 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4944 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4945
paul718e3742002-12-13 20:15:29 +00004946 /* BGP configuration. */
4947 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4948 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4949
4950 /* BGP default ipv4-unicast. */
4951 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4952 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4953
4954 /* BGP default local-preference. */
4955 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4956 vty_out (vty, " bgp default local-preference %d%s",
4957 bgp->default_local_pref, VTY_NEWLINE);
4958
4959 /* BGP client-to-client reflection. */
4960 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4961 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4962
4963 /* BGP cluster ID. */
4964 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4965 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4966 VTY_NEWLINE);
4967
hassoe0701b72004-05-20 09:19:34 +00004968 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004969 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004970 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4971 VTY_NEWLINE);
4972
4973 /* Confederation peer */
4974 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004975 {
hassoe0701b72004-05-20 09:19:34 +00004976 int i;
paul718e3742002-12-13 20:15:29 +00004977
hassoe0701b72004-05-20 09:19:34 +00004978 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004979
hassoe0701b72004-05-20 09:19:34 +00004980 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004981 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004982
hassoe0701b72004-05-20 09:19:34 +00004983 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004984 }
4985
4986 /* BGP enforce-first-as. */
4987 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4988 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4989
4990 /* BGP deterministic-med. */
4991 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4992 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004993
4994 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004995 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4996 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4997 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004998 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4999 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5000
paul718e3742002-12-13 20:15:29 +00005001 /* BGP bestpath method. */
5002 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5003 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005004 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5005 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005006 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5007 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5008 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5009 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5010 {
5011 vty_out (vty, " bgp bestpath med");
5012 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5013 vty_out (vty, " confed");
5014 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5015 vty_out (vty, " missing-as-worst");
5016 vty_out (vty, "%s", VTY_NEWLINE);
5017 }
5018
5019 /* BGP network import check. */
5020 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5021 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5022
5023 /* BGP scan interval. */
5024 bgp_config_write_scan_time (vty);
5025
5026 /* BGP flag dampening. */
5027 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5028 BGP_CONFIG_DAMPENING))
5029 bgp_config_write_damp (vty);
5030
5031 /* BGP static route configuration. */
5032 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5033
5034 /* BGP redistribute configuration. */
5035 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5036
5037 /* BGP timers configuration. */
5038 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5039 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5040 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5041 bgp->default_holdtime, VTY_NEWLINE);
5042
5043 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005044 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005045 {
5046 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5047 }
5048
5049 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005050 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005051 {
5052 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5053 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5054 }
5055
5056 /* Distance configuration. */
5057 bgp_config_write_distance (vty, bgp);
5058
5059 /* No auto-summary */
5060 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5061 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5062
5063 /* IPv4 multicast configuration. */
5064 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5065
5066 /* IPv4 VPN configuration. */
5067 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5068
5069 /* IPv6 unicast configuration. */
5070 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5071
Paul Jakma37a217a2007-04-10 19:20:29 +00005072 /* IPv6 multicast configuration. */
5073 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5074
paul718e3742002-12-13 20:15:29 +00005075 write++;
5076 }
5077 return write;
5078}
5079
5080void
paul94f2b392005-06-28 12:44:16 +00005081bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005082{
5083 memset (&bgp_master, 0, sizeof (struct bgp_master));
5084
5085 bm = &bgp_master;
5086 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005087 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005088 bm->port = BGP_PORT_DEFAULT;
5089 bm->master = thread_master_create ();
5090 bm->start_time = time (NULL);
5091}
paul200df112005-06-01 11:17:05 +00005092
paul718e3742002-12-13 20:15:29 +00005093
5094void
paul94f2b392005-06-28 12:44:16 +00005095bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005096{
paul718e3742002-12-13 20:15:29 +00005097 /* BGP VTY commands installation. */
5098 bgp_vty_init ();
5099
5100 /* Create BGP server socket. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +00005101 bgp_socket (NULL, bm->port, bm->address);
paul718e3742002-12-13 20:15:29 +00005102
5103 /* Init zebra. */
5104 bgp_zebra_init ();
5105
5106 /* BGP inits. */
5107 bgp_attr_init ();
5108 bgp_debug_init ();
5109 bgp_dump_init ();
5110 bgp_route_init ();
5111 bgp_route_map_init ();
5112 bgp_scan_init ();
5113 bgp_mplsvpn_init ();
5114
5115 /* Access list initialize. */
5116 access_list_init ();
5117 access_list_add_hook (peer_distribute_update);
5118 access_list_delete_hook (peer_distribute_update);
5119
5120 /* Filter list initialize. */
5121 bgp_filter_init ();
5122 as_list_add_hook (peer_aslist_update);
5123 as_list_delete_hook (peer_aslist_update);
5124
5125 /* Prefix list initialize.*/
5126 prefix_list_init ();
5127 prefix_list_add_hook (peer_prefix_list_update);
5128 prefix_list_delete_hook (peer_prefix_list_update);
5129
5130 /* Community list initialize. */
5131 bgp_clist = community_list_init ();
5132
5133#ifdef HAVE_SNMP
5134 bgp_snmp_init ();
5135#endif /* HAVE_SNMP */
5136}
paul545acaf2004-04-20 15:13:15 +00005137
5138void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005139bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005140{
paul545acaf2004-04-20 15:13:15 +00005141 struct bgp *bgp;
5142 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005143 struct listnode *node, *nnode;
5144 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005145
paul1eb8ef22005-04-07 07:30:20 +00005146 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5147 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005148 if (peer->status == Established)
5149 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5150 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005151
paul545acaf2004-04-20 15:13:15 +00005152 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005153
paule210cf92005-06-15 19:15:35 +00005154 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005155 {
5156 work_queue_free (bm->process_main_queue);
5157 bm->process_main_queue = NULL;
5158 }
paule210cf92005-06-15 19:15:35 +00005159 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005160 {
5161 work_queue_free (bm->process_rsclient_queue);
5162 bm->process_rsclient_queue = NULL;
5163 }
paul545acaf2004-04-20 15:13:15 +00005164}