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