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