blob: 86bf60ec1aa1b726b6ff830f8c1276adddb8243d [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 assert (peer->status != Deleted);
731
paul200df112005-06-01 11:17:05 +0000732 peer->lock++;
733
734 return peer;
735}
736
737/* decrease reference count on a struct peer
738 * struct peer is freed and NULL returned if last reference
739 */
740struct peer *
741peer_unlock (struct peer *peer)
742{
743 assert (peer && (peer->lock > 0));
744
745 peer->lock--;
746
747 if (peer->lock == 0)
748 {
749#if 0
750 zlog_debug ("unlocked and freeing");
751 zlog_backtrace (LOG_DEBUG);
752#endif
753 peer_free (peer);
754 return NULL;
755 }
756
757#if 0
758 if (peer->lock == 1)
759 {
760 zlog_debug ("unlocked to 1");
761 zlog_backtrace (LOG_DEBUG);
762 }
763#endif
764
765 return peer;
766}
767
768/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000769static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000770peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000771{
772 afi_t afi;
773 safi_t safi;
774 struct peer *peer;
775 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000776
777 /* bgp argument is absolutely required */
778 assert (bgp);
779 if (!bgp)
780 return NULL;
781
paul718e3742002-12-13 20:15:29 +0000782 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000783 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000784
785 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000786 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000787 peer->v_start = BGP_INIT_START_TIMER;
788 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
789 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
790 peer->status = Idle;
791 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000792 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000793 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000794 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000795 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700796 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000797
798 /* Set default flags. */
799 for (afi = AFI_IP; afi < AFI_MAX; afi++)
800 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
801 {
802 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
803 {
804 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
805 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
806 }
807 peer->orf_plist[afi][safi] = NULL;
808 }
809 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
810
811 /* Create buffers. */
812 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
813 peer->obuf = stream_fifo_new ();
814 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
815
816 bgp_sync_init (peer);
817
818 /* Get service port number. */
819 sp = getservbyname ("bgp", "tcp");
820 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
821
822 return peer;
823}
824
825/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000826static struct peer *
paul718e3742002-12-13 20:15:29 +0000827peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
828 as_t remote_as, afi_t afi, safi_t safi)
829{
830 int active;
831 struct peer *peer;
832 char buf[SU_ADDRSTRLEN];
833
Paul Jakma6f585442006-10-22 19:13:07 +0000834 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000835 peer->su = *su;
836 peer->local_as = local_as;
837 peer->as = remote_as;
838 peer->local_id = bgp->router_id;
839 peer->v_holdtime = bgp->default_holdtime;
840 peer->v_keepalive = bgp->default_keepalive;
841 if (peer_sort (peer) == BGP_PEER_IBGP)
842 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
843 else
844 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000845
846 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000847 listnode_add_sort (bgp->peer, peer);
848
849 active = peer_active (peer);
850
851 if (afi && safi)
852 peer->afc[afi][safi] = 1;
853
854 /* Last read time set */
855 peer->readtime = time (NULL);
856
paul848973c2003-08-13 00:32:49 +0000857 /* Last reset time set */
858 peer->resettime = time (NULL);
859
paul718e3742002-12-13 20:15:29 +0000860 /* Default TTL set. */
861 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
862
863 /* Make peer's address string. */
864 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000865 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000866
867 /* Set up peer's events and timers. */
868 if (! active && peer_active (peer))
869 bgp_timer_set (peer);
870
871 return peer;
872}
873
pauleb821182004-05-01 08:44:08 +0000874/* Make accept BGP peer. Called from bgp_accept (). */
875struct peer *
876peer_create_accept (struct bgp *bgp)
877{
878 struct peer *peer;
879
Paul Jakma6f585442006-10-22 19:13:07 +0000880 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000881
882 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000883 listnode_add_sort (bgp->peer, peer);
884
885 return peer;
886}
887
paul718e3742002-12-13 20:15:29 +0000888/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000889static void
paul718e3742002-12-13 20:15:29 +0000890peer_as_change (struct peer *peer, as_t as)
891{
892 int type;
893
894 /* Stop peer. */
895 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
896 {
897 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000898 {
899 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
900 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
901 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
902 }
paul718e3742002-12-13 20:15:29 +0000903 else
904 BGP_EVENT_ADD (peer, BGP_Stop);
905 }
906 type = peer_sort (peer);
907 peer->as = as;
908
paul848973c2003-08-13 00:32:49 +0000909 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
910 && ! bgp_confederation_peers_check (peer->bgp, as)
911 && peer->bgp->as != as)
912 peer->local_as = peer->bgp->confed_id;
913 else
914 peer->local_as = peer->bgp->as;
915
paul718e3742002-12-13 20:15:29 +0000916 /* Advertisement-interval reset */
917 if (peer_sort (peer) == BGP_PEER_IBGP)
918 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
919 else
920 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
921
922 /* TTL reset */
923 if (peer_sort (peer) == BGP_PEER_IBGP)
924 peer->ttl = 255;
925 else if (type == BGP_PEER_IBGP)
926 peer->ttl = 1;
927
928 /* reflector-client reset */
929 if (peer_sort (peer) != BGP_PEER_IBGP)
930 {
931 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
932 PEER_FLAG_REFLECTOR_CLIENT);
933 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
934 PEER_FLAG_REFLECTOR_CLIENT);
935 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
936 PEER_FLAG_REFLECTOR_CLIENT);
937 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
938 PEER_FLAG_REFLECTOR_CLIENT);
939 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
940 PEER_FLAG_REFLECTOR_CLIENT);
941 }
942
943 /* local-as reset */
944 if (peer_sort (peer) != BGP_PEER_EBGP)
945 {
946 peer->change_local_as = 0;
947 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
948 }
949}
950
951/* If peer does not exist, create new one. If peer already exists,
952 set AS number to the peer. */
953int
954peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
955 afi_t afi, safi_t safi)
956{
957 struct peer *peer;
958 as_t local_as;
959
960 peer = peer_lookup (bgp, su);
961
962 if (peer)
963 {
964 /* When this peer is a member of peer-group. */
965 if (peer->group)
966 {
967 if (peer->group->conf->as)
968 {
969 /* Return peer group's AS number. */
970 *as = peer->group->conf->as;
971 return BGP_ERR_PEER_GROUP_MEMBER;
972 }
973 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
974 {
975 if (bgp->as != *as)
976 {
977 *as = peer->as;
978 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
979 }
980 }
981 else
982 {
983 if (bgp->as == *as)
984 {
985 *as = peer->as;
986 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
987 }
988 }
989 }
990
991 /* Existing peer's AS number change. */
992 if (peer->as != *as)
993 peer_as_change (peer, *as);
994 }
995 else
996 {
997
998 /* If the peer is not part of our confederation, and its not an
999 iBGP peer then spoof the source AS */
1000 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1001 && ! bgp_confederation_peers_check (bgp, *as)
1002 && bgp->as != *as)
1003 local_as = bgp->confed_id;
1004 else
1005 local_as = bgp->as;
1006
1007 /* If this is IPv4 unicast configuration and "no bgp default
1008 ipv4-unicast" is specified. */
1009
1010 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1011 && afi == AFI_IP && safi == SAFI_UNICAST)
1012 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1013 else
1014 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1015 }
1016
1017 return 0;
1018}
1019
1020/* Activate the peer or peer group for specified AFI and SAFI. */
1021int
1022peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1023{
1024 int active;
1025
1026 if (peer->afc[afi][safi])
1027 return 0;
1028
1029 /* Activate the address family configuration. */
1030 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1031 peer->afc[afi][safi] = 1;
1032 else
1033 {
1034 active = peer_active (peer);
1035
1036 peer->afc[afi][safi] = 1;
1037
1038 if (! active && peer_active (peer))
1039 bgp_timer_set (peer);
1040 else
1041 {
1042 if (peer->status == Established)
1043 {
1044 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1045 {
1046 peer->afc_adv[afi][safi] = 1;
1047 bgp_capability_send (peer, afi, safi,
1048 CAPABILITY_CODE_MP,
1049 CAPABILITY_ACTION_SET);
1050 if (peer->afc_recv[afi][safi])
1051 {
1052 peer->afc_nego[afi][safi] = 1;
1053 bgp_announce_route (peer, afi, safi);
1054 }
1055 }
1056 else
hassoe0701b72004-05-20 09:19:34 +00001057 {
1058 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1059 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1060 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1061 }
paul718e3742002-12-13 20:15:29 +00001062 }
1063 }
1064 }
1065 return 0;
1066}
1067
1068int
1069peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1070{
1071 struct peer_group *group;
1072 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001073 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001074
1075 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1076 {
1077 group = peer->group;
1078
paul1eb8ef22005-04-07 07:30:20 +00001079 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001080 {
1081 if (peer1->af_group[afi][safi])
1082 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1083 }
1084 }
1085 else
1086 {
1087 if (peer->af_group[afi][safi])
1088 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1089 }
1090
1091 if (! peer->afc[afi][safi])
1092 return 0;
1093
1094 /* De-activate the address family configuration. */
1095 peer->afc[afi][safi] = 0;
1096 peer_af_flag_reset (peer, afi, safi);
1097
1098 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1099 {
1100 if (peer->status == Established)
1101 {
1102 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1103 {
1104 peer->afc_adv[afi][safi] = 0;
1105 peer->afc_nego[afi][safi] = 0;
1106
1107 if (peer_active_nego (peer))
1108 {
1109 bgp_capability_send (peer, afi, safi,
1110 CAPABILITY_CODE_MP,
1111 CAPABILITY_ACTION_UNSET);
1112 bgp_clear_route (peer, afi, safi);
1113 peer->pcount[afi][safi] = 0;
1114 }
1115 else
hassoe0701b72004-05-20 09:19:34 +00001116 {
1117 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1118 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1119 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1120 }
paul718e3742002-12-13 20:15:29 +00001121 }
1122 else
hassoe0701b72004-05-20 09:19:34 +00001123 {
1124 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1125 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1126 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1127 }
paul718e3742002-12-13 20:15:29 +00001128 }
1129 }
1130 return 0;
1131}
1132
hasso93406d82005-02-02 14:40:33 +00001133void
1134peer_nsf_stop (struct peer *peer)
1135{
1136 afi_t afi;
1137 safi_t safi;
1138
1139 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1140 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1141
1142 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1143 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1144 peer->nsf[afi][safi] = 0;
1145
1146 if (peer->t_gr_restart)
1147 {
1148 BGP_TIMER_OFF (peer->t_gr_restart);
1149 if (BGP_DEBUG (events, EVENTS))
1150 zlog_debug ("%s graceful restart timer stopped", peer->host);
1151 }
1152 if (peer->t_gr_stale)
1153 {
1154 BGP_TIMER_OFF (peer->t_gr_stale);
1155 if (BGP_DEBUG (events, EVENTS))
1156 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1157 }
1158 bgp_clear_route_all (peer);
1159}
1160
Paul Jakmaca058a32006-09-14 02:58:49 +00001161/* Delete peer from confguration.
1162 *
1163 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1164 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1165 *
1166 * This function /should/ take care to be idempotent, to guard against
1167 * it being called multiple times through stray events that come in
1168 * that happen to result in this function being called again. That
1169 * said, getting here for a "Deleted" peer is a bug in the neighbour
1170 * FSM.
1171 */
paul718e3742002-12-13 20:15:29 +00001172int
1173peer_delete (struct peer *peer)
1174{
1175 int i;
1176 afi_t afi;
1177 safi_t safi;
1178 struct bgp *bgp;
1179 struct bgp_filter *filter;
1180
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
paul718e3742002-12-13 20:15:29 +00001188 /* If this peer belongs to peer group. Clearn up the
1189 relationship. */
1190 if (peer->group)
1191 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001192 struct listnode *pn;
1193
1194 if ((pn = listnode_lookup (peer->group->peer, peer)))
1195 {
1196 peer = peer_unlock (peer); /* group->peer list reference */
1197 list_delete_node (peer->group->peer, pn);
1198 }
paul718e3742002-12-13 20:15:29 +00001199 peer->group = NULL;
1200 }
paul200df112005-06-01 11:17:05 +00001201
paul718e3742002-12-13 20:15:29 +00001202 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001203 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1204 * executed after peer structure is deleted.
1205 */
hassoe0701b72004-05-20 09:19:34 +00001206 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001207 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001208 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001209
1210 /* Password configuration */
1211 if (peer->password)
1212 {
1213 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1214 peer->password = NULL;
1215
1216 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1217 bgp_md5_set (peer);
1218 }
1219
Paul Jakmaca058a32006-09-14 02:58:49 +00001220 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001221
paul718e3742002-12-13 20:15:29 +00001222 /* Delete from all peer list. */
1223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001224 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001225 struct listnode *pn;
paul200df112005-06-01 11:17:05 +00001226
Paul Jakmaca058a32006-09-14 02:58:49 +00001227 if ((pn = listnode_lookup (bgp->peer, peer)))
1228 {
1229 peer_unlock (peer); /* bgp peer list reference */
1230 list_delete_node (bgp->peer, pn);
1231 }
1232
1233 if (peer_rsclient_active (peer)
1234 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001235 {
1236 peer_unlock (peer); /* rsclient list reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001237 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001238 }
paulfee0f4c2004-09-13 05:12:46 +00001239 }
1240
1241 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1242 member of a peer_group. */
1243 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1244 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1245 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001246 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001247
paul200df112005-06-01 11:17:05 +00001248 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001249 if (peer->ibuf)
1250 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001251 if (peer->obuf)
1252 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001253 if (peer->work)
1254 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001255 peer->obuf = NULL;
1256 peer->work = peer->ibuf = NULL;
1257
paul718e3742002-12-13 20:15:29 +00001258 /* Local and remote addresses. */
1259 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001260 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001261 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001262 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001263 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001264
paul718e3742002-12-13 20:15:29 +00001265 /* Free filter related memory. */
1266 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1267 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1268 {
1269 filter = &peer->filter[afi][safi];
1270
1271 for (i = FILTER_IN; i < FILTER_MAX; i++)
1272 {
1273 if (filter->dlist[i].name)
1274 free (filter->dlist[i].name);
1275 if (filter->plist[i].name)
1276 free (filter->plist[i].name);
1277 if (filter->aslist[i].name)
1278 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001279
1280 filter->dlist[i].name = NULL;
1281 filter->plist[i].name = NULL;
1282 filter->aslist[i].name = NULL;
1283 }
1284 for (i = RMAP_IN; i < RMAP_MAX; i++)
1285 {
paul718e3742002-12-13 20:15:29 +00001286 if (filter->map[i].name)
1287 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001288 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001289 }
1290
1291 if (filter->usmap.name)
1292 free (filter->usmap.name);
1293
1294 if (peer->default_rmap[afi][safi].name)
1295 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001296
1297 filter->usmap.name = NULL;
1298 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001299 }
paul200df112005-06-01 11:17:05 +00001300
1301 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001302
1303 return 0;
1304}
1305
paul94f2b392005-06-28 12:44:16 +00001306static int
paul718e3742002-12-13 20:15:29 +00001307peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1308{
1309 return strcmp (g1->name, g2->name);
1310}
1311
1312/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001313static int
paul718e3742002-12-13 20:15:29 +00001314peer_group_active (struct peer *peer)
1315{
1316 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1317 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1318 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1319 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1320 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1321 return 1;
1322 return 0;
1323}
1324
1325/* Peer group cofiguration. */
1326static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001327peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001328{
1329 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1330 sizeof (struct peer_group));
1331}
1332
paul94f2b392005-06-28 12:44:16 +00001333static void
paul718e3742002-12-13 20:15:29 +00001334peer_group_free (struct peer_group *group)
1335{
1336 XFREE (MTYPE_PEER_GROUP, group);
1337}
1338
1339struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001340peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001341{
1342 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001344
paul1eb8ef22005-04-07 07:30:20 +00001345 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001346 {
1347 if (strcmp (group->name, name) == 0)
1348 return group;
1349 }
1350 return NULL;
1351}
1352
1353struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001354peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001355{
1356 struct peer_group *group;
1357
1358 group = peer_group_lookup (bgp, name);
1359 if (group)
1360 return group;
1361
1362 group = peer_group_new ();
1363 group->bgp = bgp;
1364 group->name = strdup (name);
1365 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001366 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001367 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1368 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1369 group->conf->host = strdup (name);
paul718e3742002-12-13 20:15:29 +00001370 group->conf->group = group;
1371 group->conf->as = 0;
1372 group->conf->ttl = 1;
1373 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1374 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1375 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1376 group->conf->keepalive = 0;
1377 group->conf->holdtime = 0;
1378 group->conf->connect = 0;
1379 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1380 listnode_add_sort (bgp->group, group);
1381
1382 return 0;
1383}
1384
paul94f2b392005-06-28 12:44:16 +00001385static void
paul718e3742002-12-13 20:15:29 +00001386peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1387 afi_t afi, safi_t safi)
1388{
1389 int in = FILTER_IN;
1390 int out = FILTER_OUT;
1391 struct peer *conf;
1392 struct bgp_filter *pfilter;
1393 struct bgp_filter *gfilter;
1394
1395 conf = group->conf;
1396 pfilter = &peer->filter[afi][safi];
1397 gfilter = &conf->filter[afi][safi];
1398
1399 /* remote-as */
1400 if (conf->as)
1401 peer->as = conf->as;
1402
1403 /* remote-as */
1404 if (conf->change_local_as)
1405 peer->change_local_as = conf->change_local_as;
1406
1407 /* TTL */
1408 peer->ttl = conf->ttl;
1409
1410 /* Weight */
1411 peer->weight = conf->weight;
1412
1413 /* peer flags apply */
1414 peer->flags = conf->flags;
1415 /* peer af_flags apply */
1416 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1417 /* peer config apply */
1418 peer->config = conf->config;
1419
1420 /* peer timers apply */
1421 peer->holdtime = conf->holdtime;
1422 peer->keepalive = conf->keepalive;
1423 peer->connect = conf->connect;
1424 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1425 peer->v_connect = conf->connect;
1426 else
1427 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1428
1429 /* advertisement-interval reset */
1430 if (peer_sort (peer) == BGP_PEER_IBGP)
1431 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1432 else
1433 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1434
Paul Jakma0df7c912008-07-21 21:02:49 +00001435 /* password apply */
1436 if (peer->password)
1437 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1438
1439 if (conf->password)
1440 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1441 else
1442 peer->password = NULL;
1443
1444 bgp_md5_set (peer);
1445
paul718e3742002-12-13 20:15:29 +00001446 /* maximum-prefix */
1447 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001448 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001449 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001450
1451 /* allowas-in */
1452 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1453
paulfee0f4c2004-09-13 05:12:46 +00001454 /* route-server-client */
1455 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1456 {
1457 /* Make peer's RIB point to group's RIB. */
1458 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1459
1460 /* Import policy. */
1461 if (pfilter->map[RMAP_IMPORT].name)
1462 free (pfilter->map[RMAP_IMPORT].name);
1463 if (gfilter->map[RMAP_IMPORT].name)
1464 {
1465 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1466 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1467 }
1468 else
1469 {
1470 pfilter->map[RMAP_IMPORT].name = NULL;
1471 pfilter->map[RMAP_IMPORT].map = NULL;
1472 }
1473
1474 /* Export policy. */
1475 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1476 {
1477 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1478 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1479 }
1480 }
1481
paul718e3742002-12-13 20:15:29 +00001482 /* default-originate route-map */
1483 if (conf->default_rmap[afi][safi].name)
1484 {
1485 if (peer->default_rmap[afi][safi].name)
1486 free (peer->default_rmap[afi][safi].name);
1487 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1488 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1489 }
1490
1491 /* update-source apply */
1492 if (conf->update_source)
1493 {
1494 if (peer->update_source)
1495 sockunion_free (peer->update_source);
1496 if (peer->update_if)
1497 {
1498 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1499 peer->update_if = NULL;
1500 }
1501 peer->update_source = sockunion_dup (conf->update_source);
1502 }
1503 else if (conf->update_if)
1504 {
1505 if (peer->update_if)
1506 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1507 if (peer->update_source)
1508 {
1509 sockunion_free (peer->update_source);
1510 peer->update_source = NULL;
1511 }
1512 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1513 }
1514
1515 /* inbound filter apply */
1516 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1517 {
1518 if (pfilter->dlist[in].name)
1519 free (pfilter->dlist[in].name);
1520 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1521 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1522 }
1523 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1524 {
1525 if (pfilter->plist[in].name)
1526 free (pfilter->plist[in].name);
1527 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1528 pfilter->plist[in].plist = gfilter->plist[in].plist;
1529 }
1530 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1531 {
1532 if (pfilter->aslist[in].name)
1533 free (pfilter->aslist[in].name);
1534 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1535 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1536 }
paulfee0f4c2004-09-13 05:12:46 +00001537 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001538 {
paulfee0f4c2004-09-13 05:12:46 +00001539 if (pfilter->map[RMAP_IN].name)
1540 free (pfilter->map[RMAP_IN].name);
1541 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1542 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001543 }
1544
1545 /* outbound filter apply */
1546 if (gfilter->dlist[out].name)
1547 {
1548 if (pfilter->dlist[out].name)
1549 free (pfilter->dlist[out].name);
1550 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1551 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1552 }
1553 else
1554 {
1555 if (pfilter->dlist[out].name)
1556 free (pfilter->dlist[out].name);
1557 pfilter->dlist[out].name = NULL;
1558 pfilter->dlist[out].alist = NULL;
1559 }
1560 if (gfilter->plist[out].name)
1561 {
1562 if (pfilter->plist[out].name)
1563 free (pfilter->plist[out].name);
1564 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1565 pfilter->plist[out].plist = gfilter->plist[out].plist;
1566 }
1567 else
1568 {
1569 if (pfilter->plist[out].name)
1570 free (pfilter->plist[out].name);
1571 pfilter->plist[out].name = NULL;
1572 pfilter->plist[out].plist = NULL;
1573 }
1574 if (gfilter->aslist[out].name)
1575 {
1576 if (pfilter->aslist[out].name)
1577 free (pfilter->aslist[out].name);
1578 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1579 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1580 }
1581 else
1582 {
1583 if (pfilter->aslist[out].name)
1584 free (pfilter->aslist[out].name);
1585 pfilter->aslist[out].name = NULL;
1586 pfilter->aslist[out].aslist = NULL;
1587 }
paulfee0f4c2004-09-13 05:12:46 +00001588 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001589 {
paulfee0f4c2004-09-13 05:12:46 +00001590 if (pfilter->map[RMAP_OUT].name)
1591 free (pfilter->map[RMAP_OUT].name);
1592 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1593 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001594 }
1595 else
1596 {
paulfee0f4c2004-09-13 05:12:46 +00001597 if (pfilter->map[RMAP_OUT].name)
1598 free (pfilter->map[RMAP_OUT].name);
1599 pfilter->map[RMAP_OUT].name = NULL;
1600 pfilter->map[RMAP_OUT].map = NULL;
1601 }
1602
1603 /* RS-client's import/export route-maps. */
1604 if (gfilter->map[RMAP_IMPORT].name)
1605 {
1606 if (pfilter->map[RMAP_IMPORT].name)
1607 free (pfilter->map[RMAP_IMPORT].name);
1608 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1609 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1610 }
1611 else
1612 {
1613 if (pfilter->map[RMAP_IMPORT].name)
1614 free (pfilter->map[RMAP_IMPORT].name);
1615 pfilter->map[RMAP_IMPORT].name = NULL;
1616 pfilter->map[RMAP_IMPORT].map = NULL;
1617 }
1618 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1619 {
1620 if (pfilter->map[RMAP_EXPORT].name)
1621 free (pfilter->map[RMAP_EXPORT].name);
1622 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1623 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001624 }
1625
1626 if (gfilter->usmap.name)
1627 {
1628 if (pfilter->usmap.name)
1629 free (pfilter->usmap.name);
1630 pfilter->usmap.name = strdup (gfilter->usmap.name);
1631 pfilter->usmap.map = gfilter->usmap.map;
1632 }
1633 else
1634 {
1635 if (pfilter->usmap.name)
1636 free (pfilter->usmap.name);
1637 pfilter->usmap.name = NULL;
1638 pfilter->usmap.map = NULL;
1639 }
1640}
1641
1642/* Peer group's remote AS configuration. */
1643int
paulfd79ac92004-10-13 05:06:08 +00001644peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001645{
1646 struct peer_group *group;
1647 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001648 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001649
1650 group = peer_group_lookup (bgp, group_name);
1651 if (! group)
1652 return -1;
1653
1654 if (group->conf->as == *as)
1655 return 0;
1656
1657 /* When we setup peer-group AS number all peer group member's AS
1658 number must be updated to same number. */
1659 peer_as_change (group->conf, *as);
1660
paul1eb8ef22005-04-07 07:30:20 +00001661 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001662 {
1663 if (peer->as != *as)
1664 peer_as_change (peer, *as);
1665 }
1666
1667 return 0;
1668}
1669
1670int
1671peer_group_delete (struct peer_group *group)
1672{
1673 struct bgp *bgp;
1674 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001675 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001676
1677 bgp = group->bgp;
1678
paul1eb8ef22005-04-07 07:30:20 +00001679 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001680 {
1681 peer->group = NULL;
1682 peer_delete (peer);
1683 }
1684 list_delete (group->peer);
1685
1686 free (group->name);
1687 group->name = NULL;
1688
1689 group->conf->group = NULL;
1690 peer_delete (group->conf);
1691
1692 /* Delete from all peer_group list. */
1693 listnode_delete (bgp->group, group);
1694
1695 peer_group_free (group);
1696
1697 return 0;
1698}
1699
1700int
1701peer_group_remote_as_delete (struct peer_group *group)
1702{
1703 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001704 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001705
1706 if (! group->conf->as)
1707 return 0;
1708
paul1eb8ef22005-04-07 07:30:20 +00001709 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001710 {
1711 peer->group = NULL;
1712 peer_delete (peer);
1713 }
1714 list_delete_all_node (group->peer);
1715
1716 group->conf->as = 0;
1717
1718 return 0;
1719}
1720
1721/* Bind specified peer to peer group. */
1722int
1723peer_group_bind (struct bgp *bgp, union sockunion *su,
1724 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1725{
1726 struct peer *peer;
1727 int first_member = 0;
1728
1729 /* Check peer group's address family. */
1730 if (! group->conf->afc[afi][safi])
1731 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1732
1733 /* Lookup the peer. */
1734 peer = peer_lookup (bgp, su);
1735
1736 /* Create a new peer. */
1737 if (! peer)
1738 {
1739 if (! group->conf->as)
1740 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1741
1742 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1743 peer->group = group;
1744 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001745
Paul Jakmaca058a32006-09-14 02:58:49 +00001746 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001747 listnode_add (group->peer, peer);
1748 peer_group2peer_config_copy (group, peer, afi, safi);
1749
1750 return 0;
1751 }
1752
1753 /* When the peer already belongs to peer group, check the consistency. */
1754 if (peer->af_group[afi][safi])
1755 {
1756 if (strcmp (peer->group->name, group->name) != 0)
1757 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1758
1759 return 0;
1760 }
1761
1762 /* Check current peer group configuration. */
1763 if (peer_group_active (peer)
1764 && strcmp (peer->group->name, group->name) != 0)
1765 return BGP_ERR_PEER_GROUP_MISMATCH;
1766
1767 if (! group->conf->as)
1768 {
1769 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1770 && peer_sort (group->conf) != peer_sort (peer))
1771 {
1772 if (as)
1773 *as = peer->as;
1774 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1775 }
1776
1777 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1778 first_member = 1;
1779 }
1780
1781 peer->af_group[afi][safi] = 1;
1782 peer->afc[afi][safi] = 1;
1783 if (! peer->group)
1784 {
1785 peer->group = group;
paul200df112005-06-01 11:17:05 +00001786
Paul Jakmaca058a32006-09-14 02:58:49 +00001787 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001788 listnode_add (group->peer, peer);
1789 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001790 else
1791 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001792
1793 if (first_member)
1794 {
1795 /* Advertisement-interval reset */
1796 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1797 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1798 else
1799 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1800
1801 /* ebgp-multihop reset */
1802 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1803 group->conf->ttl = 255;
1804
1805 /* local-as reset */
1806 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1807 {
1808 group->conf->change_local_as = 0;
1809 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1810 }
1811 }
paulfee0f4c2004-09-13 05:12:46 +00001812
1813 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1814 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001815 struct listnode *pn;
1816
paulfee0f4c2004-09-13 05:12:46 +00001817 /* If it's not configured as RSERVER_CLIENT in any other address
1818 family, without being member of a peer_group, remove it from
1819 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001820 if (! peer_rsclient_active (peer)
1821 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001822 {
1823 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001824 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001825 }
paulfee0f4c2004-09-13 05:12:46 +00001826
Paul Jakmab608d5b2008-07-02 02:12:07 +00001827 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001828
1829 /* Import policy. */
1830 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1831 {
1832 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1833 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1834 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1835 }
1836
1837 /* Export policy. */
1838 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1839 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1840 {
1841 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1842 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1843 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1844 }
1845 }
1846
paul718e3742002-12-13 20:15:29 +00001847 peer_group2peer_config_copy (group, peer, afi, safi);
1848
1849 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001850 {
1851 peer->last_reset = PEER_DOWN_RMAP_BIND;
1852 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1853 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1854 }
paul718e3742002-12-13 20:15:29 +00001855 else
1856 BGP_EVENT_ADD (peer, BGP_Stop);
1857
1858 return 0;
1859}
1860
1861int
1862peer_group_unbind (struct bgp *bgp, struct peer *peer,
1863 struct peer_group *group, afi_t afi, safi_t safi)
1864{
1865 if (! peer->af_group[afi][safi])
1866 return 0;
1867
1868 if (group != peer->group)
1869 return BGP_ERR_PEER_GROUP_MISMATCH;
1870
1871 peer->af_group[afi][safi] = 0;
1872 peer->afc[afi][safi] = 0;
1873 peer_af_flag_reset (peer, afi, safi);
1874
paulfee0f4c2004-09-13 05:12:46 +00001875 if (peer->rib[afi][safi])
1876 peer->rib[afi][safi] = NULL;
1877
paul718e3742002-12-13 20:15:29 +00001878 if (! peer_group_active (peer))
1879 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001880 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001881 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001882 listnode_delete (group->peer, peer);
1883 peer->group = NULL;
1884 if (group->conf->as)
1885 {
1886 peer_delete (peer);
1887 return 0;
1888 }
1889 peer_global_config_reset (peer);
1890 }
1891
1892 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001893 {
1894 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1895 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1896 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1897 }
paul718e3742002-12-13 20:15:29 +00001898 else
1899 BGP_EVENT_ADD (peer, BGP_Stop);
1900
1901 return 0;
1902}
1903
1904/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001905static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001906bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001907{
1908 struct bgp *bgp;
1909 afi_t afi;
1910 safi_t safi;
1911
paul200df112005-06-01 11:17:05 +00001912 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1913 return NULL;
1914
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001915 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001916 bgp->peer_self = peer_new (bgp);
paulfd79ac92004-10-13 05:06:08 +00001917 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001918
1919 bgp->peer = list_new ();
1920 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1921
1922 bgp->group = list_new ();
1923 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1924
paulfee0f4c2004-09-13 05:12:46 +00001925 bgp->rsclient = list_new ();
1926 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1927
paul718e3742002-12-13 20:15:29 +00001928 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1929 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1930 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001931 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1932 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1933 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001934 }
1935
1936 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1937 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1938 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001939 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1940 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001941
1942 bgp->as = *as;
1943
1944 if (name)
1945 bgp->name = strdup (name);
1946
1947 return bgp;
1948}
1949
1950/* Return first entry of BGP. */
1951struct bgp *
paul94f2b392005-06-28 12:44:16 +00001952bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001953{
1954 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001955 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001956 return NULL;
1957}
1958
1959/* Lookup BGP entry. */
1960struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001961bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001962{
1963 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001964 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001965
paul1eb8ef22005-04-07 07:30:20 +00001966 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001967 if (bgp->as == as
1968 && ((bgp->name == NULL && name == NULL)
1969 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1970 return bgp;
1971 return NULL;
1972}
1973
1974/* Lookup BGP structure by view name. */
1975struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001976bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001977{
1978 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001979 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001980
paul1eb8ef22005-04-07 07:30:20 +00001981 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001982 if ((bgp->name == NULL && name == NULL)
1983 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1984 return bgp;
1985 return NULL;
1986}
1987
1988/* Called from VTY commands. */
1989int
paulfd79ac92004-10-13 05:06:08 +00001990bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001991{
1992 struct bgp *bgp;
1993
1994 /* Multiple instance check. */
1995 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1996 {
1997 if (name)
1998 bgp = bgp_lookup_by_name (name);
1999 else
2000 bgp = bgp_get_default ();
2001
2002 /* Already exists. */
2003 if (bgp)
2004 {
2005 if (bgp->as != *as)
2006 {
2007 *as = bgp->as;
2008 return BGP_ERR_INSTANCE_MISMATCH;
2009 }
2010 *bgp_val = bgp;
2011 return 0;
2012 }
2013 }
2014 else
2015 {
2016 /* BGP instance name can not be specified for single instance. */
2017 if (name)
2018 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2019
2020 /* Get default BGP structure if exists. */
2021 bgp = bgp_get_default ();
2022
2023 if (bgp)
2024 {
2025 if (bgp->as != *as)
2026 {
2027 *as = bgp->as;
2028 return BGP_ERR_AS_MISMATCH;
2029 }
2030 *bgp_val = bgp;
2031 return 0;
2032 }
2033 }
2034
2035 bgp = bgp_create (as, name);
2036 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002037 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002038 *bgp_val = bgp;
2039
2040 return 0;
2041}
2042
2043/* Delete BGP instance. */
2044int
2045bgp_delete (struct bgp *bgp)
2046{
2047 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002048 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002049 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002050 struct listnode *next;
2051 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002052 int i;
2053
2054 /* Delete static route. */
2055 bgp_static_delete (bgp);
2056
2057 /* Unset redistribution. */
2058 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2059 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2060 if (i != ZEBRA_ROUTE_BGP)
2061 bgp_redistribute_unset (bgp, afi, i);
2062
hassob6b7cff2005-05-26 08:29:07 +00002063 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2064 peer_group_delete (group);
paul718e3742002-12-13 20:15:29 +00002065
paul1eb8ef22005-04-07 07:30:20 +00002066 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2067 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002068
hasso54a6ed32005-05-26 22:12:33 +00002069 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2070 peer_delete (peer);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002071
2072 if (bgp->peer_self) {
2073 peer_delete(bgp->peer_self);
2074 bgp->peer_self = NULL;
2075 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002076
2077 /* Remove visibility via the master list - there may however still be
2078 * routes to be processed still referencing the struct bgp.
2079 */
2080 listnode_delete (bm->bgp, bgp);
2081
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002082 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002083
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002084 return 0;
2085}
2086
2087static void bgp_free (struct bgp *);
2088
2089void
2090bgp_lock (struct bgp *bgp)
2091{
2092 ++bgp->lock;
2093}
2094
2095void
2096bgp_unlock(struct bgp *bgp)
2097{
2098 if (--bgp->lock == 0)
2099 bgp_free (bgp);
2100}
2101
2102static void
2103bgp_free (struct bgp *bgp)
2104{
2105 afi_t afi;
2106 safi_t safi;
2107
2108 list_delete (bgp->group);
2109 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002110 list_delete (bgp->rsclient);
2111
paul718e3742002-12-13 20:15:29 +00002112 if (bgp->name)
2113 free (bgp->name);
2114
2115 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2116 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2117 {
2118 if (bgp->route[afi][safi])
2119 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2120 if (bgp->aggregate[afi][safi])
2121 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2122 if (bgp->rib[afi][safi])
2123 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2124 }
2125 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002126}
2127
2128struct peer *
2129peer_lookup (struct bgp *bgp, union sockunion *su)
2130{
2131 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002132 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002133
2134 if (! bgp)
2135 bgp = bgp_get_default ();
2136
2137 if (! bgp)
2138 return NULL;
2139
paul1eb8ef22005-04-07 07:30:20 +00002140 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002141 {
pauleb821182004-05-01 08:44:08 +00002142 if (sockunion_same (&peer->su, su)
2143 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2144 return peer;
paul718e3742002-12-13 20:15:29 +00002145 }
2146 return NULL;
2147}
2148
2149struct peer *
2150peer_lookup_with_open (union sockunion *su, as_t remote_as,
2151 struct in_addr *remote_id, int *as)
2152{
2153 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002155 struct bgp *bgp;
2156
2157 bgp = bgp_get_default ();
2158 if (! bgp)
2159 return NULL;
2160
paul1eb8ef22005-04-07 07:30:20 +00002161 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002162 {
pauleb821182004-05-01 08:44:08 +00002163 if (sockunion_same (&peer->su, su)
2164 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2165 {
2166 if (peer->as == remote_as
2167 && peer->remote_id.s_addr == remote_id->s_addr)
2168 return peer;
2169 if (peer->as == remote_as)
2170 *as = 1;
2171 }
paul718e3742002-12-13 20:15:29 +00002172 }
paul1eb8ef22005-04-07 07:30:20 +00002173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002174 {
pauleb821182004-05-01 08:44:08 +00002175 if (sockunion_same (&peer->su, su)
2176 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2177 {
2178 if (peer->as == remote_as
2179 && peer->remote_id.s_addr == 0)
2180 return peer;
2181 if (peer->as == remote_as)
2182 *as = 1;
2183 }
paul718e3742002-12-13 20:15:29 +00002184 }
2185 return NULL;
2186}
2187
2188/* If peer is configured at least one address family return 1. */
2189int
2190peer_active (struct peer *peer)
2191{
2192 if (peer->afc[AFI_IP][SAFI_UNICAST]
2193 || peer->afc[AFI_IP][SAFI_MULTICAST]
2194 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2195 || peer->afc[AFI_IP6][SAFI_UNICAST]
2196 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2197 return 1;
2198 return 0;
2199}
2200
2201/* If peer is negotiated at least one address family return 1. */
2202int
2203peer_active_nego (struct peer *peer)
2204{
2205 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2206 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2207 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2208 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2209 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2210 return 1;
2211 return 0;
2212}
2213
2214/* peer_flag_change_type. */
2215enum peer_change_type
2216{
2217 peer_change_none,
2218 peer_change_reset,
2219 peer_change_reset_in,
2220 peer_change_reset_out,
2221};
2222
paul94f2b392005-06-28 12:44:16 +00002223static void
paul718e3742002-12-13 20:15:29 +00002224peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2225 enum peer_change_type type)
2226{
2227 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2228 return;
2229
2230 if (type == peer_change_reset)
2231 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2232 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2233 else if (type == peer_change_reset_in)
2234 {
2235 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2236 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2237 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2238 else
2239 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2240 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2241 }
2242 else if (type == peer_change_reset_out)
2243 bgp_announce_route (peer, afi, safi);
2244}
2245
2246struct peer_flag_action
2247{
2248 /* Peer's flag. */
2249 u_int32_t flag;
2250
2251 /* This flag can be set for peer-group member. */
2252 u_char not_for_member;
2253
2254 /* Action when the flag is changed. */
2255 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002256
2257 /* Peer down cause */
2258 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002259};
2260
2261struct peer_flag_action peer_flag_action_list[] =
2262 {
2263 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2264 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2265 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2266 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2267 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002268 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002269 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002270 { 0, 0, 0 }
2271 };
2272
2273struct peer_flag_action peer_af_flag_action_list[] =
2274 {
2275 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2276 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2277 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2278 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2279 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2280 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2281 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2282 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2283 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2284 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2285 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2286 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2287 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002288 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002289 { 0, 0, 0 }
2290 };
2291
2292/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002293static int
paul718e3742002-12-13 20:15:29 +00002294peer_flag_action_set (struct peer_flag_action *action_list, int size,
2295 struct peer_flag_action *action, u_int32_t flag)
2296{
2297 int i;
2298 int found = 0;
2299 int reset_in = 0;
2300 int reset_out = 0;
2301 struct peer_flag_action *match = NULL;
2302
2303 /* Check peer's frag action. */
2304 for (i = 0; i < size; i++)
2305 {
2306 match = &action_list[i];
2307
2308 if (match->flag == 0)
2309 break;
2310
2311 if (match->flag & flag)
2312 {
2313 found = 1;
2314
2315 if (match->type == peer_change_reset_in)
2316 reset_in = 1;
2317 if (match->type == peer_change_reset_out)
2318 reset_out = 1;
2319 if (match->type == peer_change_reset)
2320 {
2321 reset_in = 1;
2322 reset_out = 1;
2323 }
2324 if (match->not_for_member)
2325 action->not_for_member = 1;
2326 }
2327 }
2328
2329 /* Set peer clear type. */
2330 if (reset_in && reset_out)
2331 action->type = peer_change_reset;
2332 else if (reset_in)
2333 action->type = peer_change_reset_in;
2334 else if (reset_out)
2335 action->type = peer_change_reset_out;
2336 else
2337 action->type = peer_change_none;
2338
2339 return found;
2340}
2341
paul94f2b392005-06-28 12:44:16 +00002342static void
paul718e3742002-12-13 20:15:29 +00002343peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2344{
2345 if (flag == PEER_FLAG_SHUTDOWN)
2346 {
2347 if (CHECK_FLAG (peer->flags, flag))
2348 {
hasso93406d82005-02-02 14:40:33 +00002349 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2350 peer_nsf_stop (peer);
2351
hasso0a486e52005-02-01 20:57:17 +00002352 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2353 if (peer->t_pmax_restart)
2354 {
2355 BGP_TIMER_OFF (peer->t_pmax_restart);
2356 if (BGP_DEBUG (events, EVENTS))
2357 zlog_debug ("%s Maximum-prefix restart timer canceled",
2358 peer->host);
2359 }
2360
hasso93406d82005-02-02 14:40:33 +00002361 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2362 peer_nsf_stop (peer);
2363
paul718e3742002-12-13 20:15:29 +00002364 if (peer->status == Established)
2365 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2366 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2367 else
2368 BGP_EVENT_ADD (peer, BGP_Stop);
2369 }
2370 else
2371 {
2372 peer->v_start = BGP_INIT_START_TIMER;
2373 BGP_EVENT_ADD (peer, BGP_Stop);
2374 }
2375 }
2376 else if (peer->status == Established)
2377 {
hassoc9502432005-02-01 22:01:48 +00002378 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2379 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2380 else if (flag == PEER_FLAG_PASSIVE)
2381 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002382 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002383 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002384
hassoc9502432005-02-01 22:01:48 +00002385 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2386 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002387 }
2388 else
2389 BGP_EVENT_ADD (peer, BGP_Stop);
2390}
2391
2392/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002393static int
paul718e3742002-12-13 20:15:29 +00002394peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2395{
2396 int found;
2397 int size;
2398 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002399 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002400 struct peer_flag_action action;
2401
2402 memset (&action, 0, sizeof (struct peer_flag_action));
2403 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2404
2405 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2406
2407 /* No flag action is found. */
2408 if (! found)
2409 return BGP_ERR_INVALID_FLAG;
2410
2411 /* Not for peer-group member. */
2412 if (action.not_for_member && peer_group_active (peer))
2413 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2414
2415 /* When unset the peer-group member's flag we have to check
2416 peer-group configuration. */
2417 if (! set && peer_group_active (peer))
2418 if (CHECK_FLAG (peer->group->conf->flags, flag))
2419 {
2420 if (flag == PEER_FLAG_SHUTDOWN)
2421 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2422 else
2423 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2424 }
2425
2426 /* Flag conflict check. */
2427 if (set
2428 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2429 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2430 return BGP_ERR_PEER_FLAG_CONFLICT;
2431
2432 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2433 {
2434 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2435 return 0;
2436 if (! set && ! CHECK_FLAG (peer->flags, flag))
2437 return 0;
2438 }
2439
2440 if (set)
2441 SET_FLAG (peer->flags, flag);
2442 else
2443 UNSET_FLAG (peer->flags, flag);
2444
2445 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2446 {
2447 if (action.type == peer_change_reset)
2448 peer_flag_modify_action (peer, flag);
2449
2450 return 0;
2451 }
2452
2453 /* peer-group member updates. */
2454 group = peer->group;
2455
paul1eb8ef22005-04-07 07:30:20 +00002456 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002457 {
2458 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2459 continue;
2460
2461 if (! set && ! CHECK_FLAG (peer->flags, flag))
2462 continue;
2463
2464 if (set)
2465 SET_FLAG (peer->flags, flag);
2466 else
2467 UNSET_FLAG (peer->flags, flag);
2468
2469 if (action.type == peer_change_reset)
2470 peer_flag_modify_action (peer, flag);
2471 }
2472 return 0;
2473}
2474
2475int
2476peer_flag_set (struct peer *peer, u_int32_t flag)
2477{
2478 return peer_flag_modify (peer, flag, 1);
2479}
2480
2481int
2482peer_flag_unset (struct peer *peer, u_int32_t flag)
2483{
2484 return peer_flag_modify (peer, flag, 0);
2485}
2486
paul94f2b392005-06-28 12:44:16 +00002487static int
paul718e3742002-12-13 20:15:29 +00002488peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2489{
2490 if (peer->af_group[afi][safi])
2491 return 1;
2492 return 0;
2493}
2494
paul94f2b392005-06-28 12:44:16 +00002495static int
paul718e3742002-12-13 20:15:29 +00002496peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2497 int set)
2498{
2499 int found;
2500 int size;
paul1eb8ef22005-04-07 07:30:20 +00002501 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002502 struct peer_group *group;
2503 struct peer_flag_action action;
2504
2505 memset (&action, 0, sizeof (struct peer_flag_action));
2506 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2507
2508 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2509
2510 /* No flag action is found. */
2511 if (! found)
2512 return BGP_ERR_INVALID_FLAG;
2513
2514 /* Adress family must be activated. */
2515 if (! peer->afc[afi][safi])
2516 return BGP_ERR_PEER_INACTIVE;
2517
2518 /* Not for peer-group member. */
2519 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2520 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2521
2522 /* Spcecial check for reflector client. */
2523 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2524 && peer_sort (peer) != BGP_PEER_IBGP)
2525 return BGP_ERR_NOT_INTERNAL_PEER;
2526
2527 /* Spcecial check for remove-private-AS. */
2528 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2529 && peer_sort (peer) == BGP_PEER_IBGP)
2530 return BGP_ERR_REMOVE_PRIVATE_AS;
2531
2532 /* When unset the peer-group member's flag we have to check
2533 peer-group configuration. */
2534 if (! set && peer->af_group[afi][safi])
2535 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2536 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2537
2538 /* When current flag configuration is same as requested one. */
2539 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2540 {
2541 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2542 return 0;
2543 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2544 return 0;
2545 }
2546
2547 if (set)
2548 SET_FLAG (peer->af_flags[afi][safi], flag);
2549 else
2550 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2551
2552 /* Execute action when peer is established. */
2553 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2554 && peer->status == Established)
2555 {
2556 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2557 bgp_clear_adj_in (peer, afi, safi);
2558 else
hassoe0701b72004-05-20 09:19:34 +00002559 {
2560 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2561 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2562 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2563 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2564 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2565 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2566 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2567 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2568
2569 peer_change_action (peer, afi, safi, action.type);
2570 }
2571
paul718e3742002-12-13 20:15:29 +00002572 }
2573
2574 /* Peer group member updates. */
2575 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2576 {
2577 group = peer->group;
2578
paul1eb8ef22005-04-07 07:30:20 +00002579 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002580 {
2581 if (! peer->af_group[afi][safi])
2582 continue;
2583
2584 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2585 continue;
2586
2587 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2588 continue;
2589
2590 if (set)
2591 SET_FLAG (peer->af_flags[afi][safi], flag);
2592 else
2593 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2594
2595 if (peer->status == Established)
2596 {
2597 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2598 bgp_clear_adj_in (peer, afi, safi);
2599 else
hassoe0701b72004-05-20 09:19:34 +00002600 {
2601 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2602 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2603 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2604 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2605 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2606 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2607 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2608 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2609
2610 peer_change_action (peer, afi, safi, action.type);
2611 }
paul718e3742002-12-13 20:15:29 +00002612 }
2613 }
2614 }
2615 return 0;
2616}
2617
2618int
2619peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2620{
2621 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2622}
2623
2624int
2625peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2626{
2627 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2628}
2629
2630/* EBGP multihop configuration. */
2631int
2632peer_ebgp_multihop_set (struct peer *peer, int ttl)
2633{
2634 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002635 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002636
2637 if (peer_sort (peer) == BGP_PEER_IBGP)
2638 return 0;
2639
2640 peer->ttl = ttl;
2641
2642 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2643 {
pauleb821182004-05-01 08:44:08 +00002644 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2645 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002646 }
2647 else
2648 {
2649 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002650 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002651 {
2652 if (peer_sort (peer) == BGP_PEER_IBGP)
2653 continue;
paul718e3742002-12-13 20:15:29 +00002654
pauleb821182004-05-01 08:44:08 +00002655 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002656
pauleb821182004-05-01 08:44:08 +00002657 if (peer->fd >= 0)
2658 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2659 }
paul718e3742002-12-13 20:15:29 +00002660 }
2661 return 0;
2662}
2663
2664int
2665peer_ebgp_multihop_unset (struct peer *peer)
2666{
2667 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002668 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002669
2670 if (peer_sort (peer) == BGP_PEER_IBGP)
2671 return 0;
2672
2673 if (peer_group_active (peer))
2674 peer->ttl = peer->group->conf->ttl;
2675 else
2676 peer->ttl = 1;
2677
2678 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2679 {
pauleb821182004-05-01 08:44:08 +00002680 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2681 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002682 }
2683 else
2684 {
2685 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002686 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002687 {
2688 if (peer_sort (peer) == BGP_PEER_IBGP)
2689 continue;
paul718e3742002-12-13 20:15:29 +00002690
pauleb821182004-05-01 08:44:08 +00002691 peer->ttl = 1;
2692
2693 if (peer->fd >= 0)
2694 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2695 }
paul718e3742002-12-13 20:15:29 +00002696 }
2697 return 0;
2698}
2699
2700/* Neighbor description. */
2701int
2702peer_description_set (struct peer *peer, char *desc)
2703{
2704 if (peer->desc)
2705 XFREE (MTYPE_PEER_DESC, peer->desc);
2706
2707 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2708
2709 return 0;
2710}
2711
2712int
2713peer_description_unset (struct peer *peer)
2714{
2715 if (peer->desc)
2716 XFREE (MTYPE_PEER_DESC, peer->desc);
2717
2718 peer->desc = NULL;
2719
2720 return 0;
2721}
2722
2723/* Neighbor update-source. */
2724int
paulfd79ac92004-10-13 05:06:08 +00002725peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002726{
2727 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002728 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002729
2730 if (peer->update_if)
2731 {
2732 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2733 && strcmp (peer->update_if, ifname) == 0)
2734 return 0;
2735
2736 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2737 peer->update_if = NULL;
2738 }
2739
2740 if (peer->update_source)
2741 {
2742 sockunion_free (peer->update_source);
2743 peer->update_source = NULL;
2744 }
2745
2746 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2747
2748 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2749 {
2750 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002751 {
2752 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2753 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2754 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2755 }
paul718e3742002-12-13 20:15:29 +00002756 else
2757 BGP_EVENT_ADD (peer, BGP_Stop);
2758 return 0;
2759 }
2760
2761 /* peer-group member updates. */
2762 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002763 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002764 {
2765 if (peer->update_if)
2766 {
2767 if (strcmp (peer->update_if, ifname) == 0)
2768 continue;
2769
2770 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2771 peer->update_if = NULL;
2772 }
2773
2774 if (peer->update_source)
2775 {
2776 sockunion_free (peer->update_source);
2777 peer->update_source = NULL;
2778 }
2779
2780 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2781
2782 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002783 {
2784 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2785 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2786 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2787 }
paul718e3742002-12-13 20:15:29 +00002788 else
2789 BGP_EVENT_ADD (peer, BGP_Stop);
2790 }
2791 return 0;
2792}
2793
2794int
2795peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2796{
2797 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002798 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002799
2800 if (peer->update_source)
2801 {
2802 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2803 && sockunion_cmp (peer->update_source, su) == 0)
2804 return 0;
2805 sockunion_free (peer->update_source);
2806 peer->update_source = NULL;
2807 }
2808
2809 if (peer->update_if)
2810 {
2811 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2812 peer->update_if = NULL;
2813 }
2814
2815 peer->update_source = sockunion_dup (su);
2816
2817 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2818 {
2819 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002820 {
2821 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2822 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2823 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2824 }
paul718e3742002-12-13 20:15:29 +00002825 else
2826 BGP_EVENT_ADD (peer, BGP_Stop);
2827 return 0;
2828 }
2829
2830 /* peer-group member updates. */
2831 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002832 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002833 {
2834 if (peer->update_source)
2835 {
2836 if (sockunion_cmp (peer->update_source, su) == 0)
2837 continue;
2838 sockunion_free (peer->update_source);
2839 peer->update_source = NULL;
2840 }
2841
2842 if (peer->update_if)
2843 {
2844 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2845 peer->update_if = NULL;
2846 }
2847
2848 peer->update_source = sockunion_dup (su);
2849
2850 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002851 {
2852 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2853 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2854 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2855 }
paul718e3742002-12-13 20:15:29 +00002856 else
2857 BGP_EVENT_ADD (peer, BGP_Stop);
2858 }
2859 return 0;
2860}
2861
2862int
2863peer_update_source_unset (struct peer *peer)
2864{
2865 union sockunion *su;
2866 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002867 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002868
2869 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2870 && ! peer->update_source
2871 && ! peer->update_if)
2872 return 0;
2873
2874 if (peer->update_source)
2875 {
2876 sockunion_free (peer->update_source);
2877 peer->update_source = NULL;
2878 }
2879 if (peer->update_if)
2880 {
2881 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2882 peer->update_if = NULL;
2883 }
2884
2885 if (peer_group_active (peer))
2886 {
2887 group = peer->group;
2888
2889 if (group->conf->update_source)
2890 {
2891 su = sockunion_dup (group->conf->update_source);
2892 peer->update_source = su;
2893 }
2894 else if (group->conf->update_if)
2895 peer->update_if =
2896 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2897 }
2898
2899 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2900 {
2901 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002902 {
2903 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2904 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2905 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2906 }
paul718e3742002-12-13 20:15:29 +00002907 else
2908 BGP_EVENT_ADD (peer, BGP_Stop);
2909 return 0;
2910 }
2911
2912 /* peer-group member updates. */
2913 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002914 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002915 {
2916 if (! peer->update_source && ! peer->update_if)
2917 continue;
2918
2919 if (peer->update_source)
2920 {
2921 sockunion_free (peer->update_source);
2922 peer->update_source = NULL;
2923 }
2924
2925 if (peer->update_if)
2926 {
2927 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2928 peer->update_if = NULL;
2929 }
2930
2931 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002932 {
2933 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2934 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2935 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2936 }
paul718e3742002-12-13 20:15:29 +00002937 else
2938 BGP_EVENT_ADD (peer, BGP_Stop);
2939 }
2940 return 0;
2941}
2942
2943int
2944peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002945 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002946{
2947 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002948 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002949
2950 /* Adress family must be activated. */
2951 if (! peer->afc[afi][safi])
2952 return BGP_ERR_PEER_INACTIVE;
2953
2954 /* Default originate can't be used for peer group memeber. */
2955 if (peer_is_group_member (peer, afi, safi))
2956 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2957
2958 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2959 || (rmap && ! peer->default_rmap[afi][safi].name)
2960 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2961 {
2962 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2963
2964 if (rmap)
2965 {
2966 if (peer->default_rmap[afi][safi].name)
2967 free (peer->default_rmap[afi][safi].name);
2968 peer->default_rmap[afi][safi].name = strdup (rmap);
2969 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2970 }
2971 }
2972
2973 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2974 {
2975 if (peer->status == Established && peer->afc_nego[afi][safi])
2976 bgp_default_originate (peer, afi, safi, 0);
2977 return 0;
2978 }
2979
2980 /* peer-group member updates. */
2981 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002982 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002983 {
2984 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2985
2986 if (rmap)
2987 {
2988 if (peer->default_rmap[afi][safi].name)
2989 free (peer->default_rmap[afi][safi].name);
2990 peer->default_rmap[afi][safi].name = strdup (rmap);
2991 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2992 }
2993
2994 if (peer->status == Established && peer->afc_nego[afi][safi])
2995 bgp_default_originate (peer, afi, safi, 0);
2996 }
2997 return 0;
2998}
2999
3000int
3001peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3002{
3003 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003005
3006 /* Adress family must be activated. */
3007 if (! peer->afc[afi][safi])
3008 return BGP_ERR_PEER_INACTIVE;
3009
3010 /* Default originate can't be used for peer group memeber. */
3011 if (peer_is_group_member (peer, afi, safi))
3012 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3013
3014 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3015 {
3016 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3017
3018 if (peer->default_rmap[afi][safi].name)
3019 free (peer->default_rmap[afi][safi].name);
3020 peer->default_rmap[afi][safi].name = NULL;
3021 peer->default_rmap[afi][safi].map = NULL;
3022 }
3023
3024 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3025 {
3026 if (peer->status == Established && peer->afc_nego[afi][safi])
3027 bgp_default_originate (peer, afi, safi, 1);
3028 return 0;
3029 }
3030
3031 /* peer-group member updates. */
3032 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003033 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003034 {
3035 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3036
3037 if (peer->default_rmap[afi][safi].name)
3038 free (peer->default_rmap[afi][safi].name);
3039 peer->default_rmap[afi][safi].name = NULL;
3040 peer->default_rmap[afi][safi].map = NULL;
3041
3042 if (peer->status == Established && peer->afc_nego[afi][safi])
3043 bgp_default_originate (peer, afi, safi, 1);
3044 }
3045 return 0;
3046}
3047
3048int
3049peer_port_set (struct peer *peer, u_int16_t port)
3050{
3051 peer->port = port;
3052 return 0;
3053}
3054
3055int
3056peer_port_unset (struct peer *peer)
3057{
3058 peer->port = BGP_PORT_DEFAULT;
3059 return 0;
3060}
3061
3062/* neighbor weight. */
3063int
3064peer_weight_set (struct peer *peer, u_int16_t weight)
3065{
3066 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003067 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003068
3069 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3070 peer->weight = weight;
3071
3072 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3073 return 0;
3074
3075 /* peer-group member updates. */
3076 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003077 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003078 {
3079 peer->weight = group->conf->weight;
3080 }
3081 return 0;
3082}
3083
3084int
3085peer_weight_unset (struct peer *peer)
3086{
3087 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003088 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003089
3090 /* Set default weight. */
3091 if (peer_group_active (peer))
3092 peer->weight = peer->group->conf->weight;
3093 else
3094 peer->weight = 0;
3095
3096 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3097
3098 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3099 return 0;
3100
3101 /* peer-group member updates. */
3102 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003103 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003104 {
3105 peer->weight = 0;
3106 }
3107 return 0;
3108}
3109
3110int
3111peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3112{
3113 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003114 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003115
3116 /* Not for peer group memeber. */
3117 if (peer_group_active (peer))
3118 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3119
3120 /* keepalive value check. */
3121 if (keepalive > 65535)
3122 return BGP_ERR_INVALID_VALUE;
3123
3124 /* Holdtime value check. */
3125 if (holdtime > 65535)
3126 return BGP_ERR_INVALID_VALUE;
3127
3128 /* Holdtime value must be either 0 or greater than 3. */
3129 if (holdtime < 3 && holdtime != 0)
3130 return BGP_ERR_INVALID_VALUE;
3131
3132 /* Set value to the configuration. */
3133 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3134 peer->holdtime = holdtime;
3135 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3136
3137 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3138 return 0;
3139
3140 /* peer-group member updates. */
3141 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003142 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003143 {
3144 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3145 peer->holdtime = group->conf->holdtime;
3146 peer->keepalive = group->conf->keepalive;
3147 }
3148 return 0;
3149}
3150
3151int
3152peer_timers_unset (struct peer *peer)
3153{
3154 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003156
3157 if (peer_group_active (peer))
3158 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3159
3160 /* Clear configuration. */
3161 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3162 peer->keepalive = 0;
3163 peer->holdtime = 0;
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 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3173 peer->holdtime = 0;
3174 peer->keepalive = 0;
3175 }
3176
3177 return 0;
3178}
3179
3180int
3181peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3182{
3183 if (peer_group_active (peer))
3184 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3185
3186 if (connect > 65535)
3187 return BGP_ERR_INVALID_VALUE;
3188
3189 /* Set value to the configuration. */
3190 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3191 peer->connect = connect;
3192
3193 /* Set value to timer setting. */
3194 peer->v_connect = connect;
3195
3196 return 0;
3197}
3198
3199int
3200peer_timers_connect_unset (struct peer *peer)
3201{
3202 if (peer_group_active (peer))
3203 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3204
3205 /* Clear configuration. */
3206 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3207 peer->connect = 0;
3208
3209 /* Set timer setting to default value. */
3210 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3211
3212 return 0;
3213}
3214
3215int
3216peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3217{
3218 if (peer_group_active (peer))
3219 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3220
3221 if (routeadv > 600)
3222 return BGP_ERR_INVALID_VALUE;
3223
3224 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3225 peer->routeadv = routeadv;
3226 peer->v_routeadv = routeadv;
3227
3228 return 0;
3229}
3230
3231int
3232peer_advertise_interval_unset (struct peer *peer)
3233{
3234 if (peer_group_active (peer))
3235 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3236
3237 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3238 peer->routeadv = 0;
3239
3240 if (peer_sort (peer) == BGP_PEER_IBGP)
3241 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3242 else
3243 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3244
3245 return 0;
3246}
3247
paul718e3742002-12-13 20:15:29 +00003248/* neighbor interface */
3249int
paulfd79ac92004-10-13 05:06:08 +00003250peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003251{
3252 if (peer->ifname)
3253 free (peer->ifname);
3254 peer->ifname = strdup (str);
3255
3256 return 0;
3257}
3258
3259int
3260peer_interface_unset (struct peer *peer)
3261{
3262 if (peer->ifname)
3263 free (peer->ifname);
3264 peer->ifname = NULL;
3265
3266 return 0;
3267}
3268
3269/* Allow-as in. */
3270int
3271peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3272{
3273 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003274 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003275
3276 if (allow_num < 1 || allow_num > 10)
3277 return BGP_ERR_INVALID_VALUE;
3278
3279 if (peer->allowas_in[afi][safi] != allow_num)
3280 {
3281 peer->allowas_in[afi][safi] = allow_num;
3282 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3283 peer_change_action (peer, afi, safi, peer_change_reset_in);
3284 }
3285
3286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3287 return 0;
3288
3289 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003290 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003291 {
3292 if (peer->allowas_in[afi][safi] != allow_num)
3293 {
3294 peer->allowas_in[afi][safi] = allow_num;
3295 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3296 peer_change_action (peer, afi, safi, peer_change_reset_in);
3297 }
3298
3299 }
3300 return 0;
3301}
3302
3303int
3304peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3305{
3306 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003307 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003308
3309 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3310 {
3311 peer->allowas_in[afi][safi] = 0;
3312 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3313 }
3314
3315 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3316 return 0;
3317
3318 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003319 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003320 {
3321 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3322 {
3323 peer->allowas_in[afi][safi] = 0;
3324 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3325 }
3326 }
3327 return 0;
3328}
3329
3330int
3331peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3332{
3333 struct bgp *bgp = peer->bgp;
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 (peer_sort (peer) != BGP_PEER_EBGP
3338 && peer_sort (peer) != BGP_PEER_INTERNAL)
3339 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3340
3341 if (bgp->as == as)
3342 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3343
3344 if (peer_group_active (peer))
3345 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3346
3347 if (peer->change_local_as == as &&
3348 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3349 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3350 return 0;
3351
3352 peer->change_local_as = as;
3353 if (no_prepend)
3354 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3355 else
3356 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3357
3358 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3359 {
3360 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003361 {
3362 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3363 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3364 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3365 }
paul718e3742002-12-13 20:15:29 +00003366 else
3367 BGP_EVENT_ADD (peer, BGP_Stop);
3368
3369 return 0;
3370 }
3371
3372 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003373 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003374 {
3375 peer->change_local_as = as;
3376 if (no_prepend)
3377 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3378 else
3379 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3380
3381 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003382 {
3383 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3384 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3385 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3386 }
paul718e3742002-12-13 20:15:29 +00003387 else
3388 BGP_EVENT_ADD (peer, BGP_Stop);
3389 }
3390
3391 return 0;
3392}
3393
3394int
3395peer_local_as_unset (struct peer *peer)
3396{
3397 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003398 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003399
3400 if (peer_group_active (peer))
3401 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3402
3403 if (! peer->change_local_as)
3404 return 0;
3405
3406 peer->change_local_as = 0;
3407 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3408
3409 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3410 {
3411 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003412 {
3413 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3414 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3415 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3416 }
paul718e3742002-12-13 20:15:29 +00003417 else
3418 BGP_EVENT_ADD (peer, BGP_Stop);
3419
3420 return 0;
3421 }
3422
3423 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003424 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003425 {
3426 peer->change_local_as = 0;
3427 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3428
3429 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003430 {
3431 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3432 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3433 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3434 }
paul718e3742002-12-13 20:15:29 +00003435 else
3436 BGP_EVENT_ADD (peer, BGP_Stop);
3437 }
3438 return 0;
3439}
3440
Paul Jakma0df7c912008-07-21 21:02:49 +00003441/* Set password for authenticating with the peer. */
3442int
3443peer_password_set (struct peer *peer, const char *password)
3444{
3445 struct listnode *nn, *nnode;
3446 int len = password ? strlen(password) : 0;
3447 int ret = BGP_SUCCESS;
3448
3449 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3450 return BGP_ERR_INVALID_VALUE;
3451
3452 if (peer->password && strcmp (peer->password, password) == 0
3453 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3454 return 0;
3455
3456 if (peer->password)
3457 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3458
3459 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3460
3461 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3462 {
3463 if (peer->status == Established)
3464 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3465 else
3466 BGP_EVENT_ADD (peer, BGP_Stop);
3467
3468 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3469 }
3470
3471 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3472 {
3473 if (peer->password && strcmp (peer->password, password) == 0)
3474 continue;
3475
3476 if (peer->password)
3477 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3478
3479 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3480
3481 if (peer->status == Established)
3482 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3483 else
3484 BGP_EVENT_ADD (peer, BGP_Stop);
3485
3486 if (bgp_md5_set (peer) < 0)
3487 ret = BGP_ERR_TCPSIG_FAILED;
3488 }
3489
3490 return ret;
3491}
3492
3493int
3494peer_password_unset (struct peer *peer)
3495{
3496 struct listnode *nn, *nnode;
3497
3498 if (!peer->password
3499 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3500 return 0;
3501
3502 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3503 {
3504 if (peer_group_active (peer)
3505 && peer->group->conf->password
3506 && strcmp (peer->group->conf->password, peer->password) == 0)
3507 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
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 (peer->password)
3515 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3516
3517 peer->password = NULL;
3518
3519 bgp_md5_set (peer);
3520
3521 return 0;
3522 }
3523
3524 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3525 peer->password = NULL;
3526
3527 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3528 {
3529 if (!peer->password)
3530 continue;
3531
3532 if (peer->status == Established)
3533 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3534 else
3535 BGP_EVENT_ADD (peer, BGP_Stop);
3536
3537 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3538 peer->password = NULL;
3539
3540 bgp_md5_set (peer);
3541 }
3542
3543 return 0;
3544}
3545
paul718e3742002-12-13 20:15:29 +00003546/* Set distribute list to the peer. */
3547int
3548peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003549 const char *name)
paul718e3742002-12-13 20:15:29 +00003550{
3551 struct bgp_filter *filter;
3552 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003553 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003554
3555 if (! peer->afc[afi][safi])
3556 return BGP_ERR_PEER_INACTIVE;
3557
3558 if (direct != FILTER_IN && direct != FILTER_OUT)
3559 return BGP_ERR_INVALID_VALUE;
3560
3561 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3562 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3563
3564 filter = &peer->filter[afi][safi];
3565
3566 if (filter->plist[direct].name)
3567 return BGP_ERR_PEER_FILTER_CONFLICT;
3568
3569 if (filter->dlist[direct].name)
3570 free (filter->dlist[direct].name);
3571 filter->dlist[direct].name = strdup (name);
3572 filter->dlist[direct].alist = access_list_lookup (afi, name);
3573
3574 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3575 return 0;
3576
3577 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003578 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003579 {
3580 filter = &peer->filter[afi][safi];
3581
3582 if (! peer->af_group[afi][safi])
3583 continue;
3584
3585 if (filter->dlist[direct].name)
3586 free (filter->dlist[direct].name);
3587 filter->dlist[direct].name = strdup (name);
3588 filter->dlist[direct].alist = access_list_lookup (afi, name);
3589 }
3590
3591 return 0;
3592}
3593
3594int
3595peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3596{
3597 struct bgp_filter *filter;
3598 struct bgp_filter *gfilter;
3599 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003600 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003601
3602 if (! peer->afc[afi][safi])
3603 return BGP_ERR_PEER_INACTIVE;
3604
3605 if (direct != FILTER_IN && direct != FILTER_OUT)
3606 return BGP_ERR_INVALID_VALUE;
3607
3608 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3609 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3610
3611 filter = &peer->filter[afi][safi];
3612
3613 /* apply peer-group filter */
3614 if (peer->af_group[afi][safi])
3615 {
3616 gfilter = &peer->group->conf->filter[afi][safi];
3617
3618 if (gfilter->dlist[direct].name)
3619 {
3620 if (filter->dlist[direct].name)
3621 free (filter->dlist[direct].name);
3622 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3623 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3624 return 0;
3625 }
3626 }
3627
3628 if (filter->dlist[direct].name)
3629 free (filter->dlist[direct].name);
3630 filter->dlist[direct].name = NULL;
3631 filter->dlist[direct].alist = NULL;
3632
3633 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3634 return 0;
3635
3636 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003637 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003638 {
3639 filter = &peer->filter[afi][safi];
3640
3641 if (! peer->af_group[afi][safi])
3642 continue;
3643
3644 if (filter->dlist[direct].name)
3645 free (filter->dlist[direct].name);
3646 filter->dlist[direct].name = NULL;
3647 filter->dlist[direct].alist = NULL;
3648 }
3649
3650 return 0;
3651}
3652
3653/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003654static void
paul718e3742002-12-13 20:15:29 +00003655peer_distribute_update (struct access_list *access)
3656{
3657 afi_t afi;
3658 safi_t safi;
3659 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003660 struct listnode *mnode, *mnnode;
3661 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003662 struct bgp *bgp;
3663 struct peer *peer;
3664 struct peer_group *group;
3665 struct bgp_filter *filter;
3666
paul1eb8ef22005-04-07 07:30:20 +00003667 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003668 {
paul1eb8ef22005-04-07 07:30:20 +00003669 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003670 {
3671 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3672 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3673 {
3674 filter = &peer->filter[afi][safi];
3675
3676 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3677 {
3678 if (filter->dlist[direct].name)
3679 filter->dlist[direct].alist =
3680 access_list_lookup (afi, filter->dlist[direct].name);
3681 else
3682 filter->dlist[direct].alist = NULL;
3683 }
3684 }
3685 }
paul1eb8ef22005-04-07 07:30:20 +00003686 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003687 {
3688 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3689 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3690 {
3691 filter = &group->conf->filter[afi][safi];
3692
3693 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3694 {
3695 if (filter->dlist[direct].name)
3696 filter->dlist[direct].alist =
3697 access_list_lookup (afi, filter->dlist[direct].name);
3698 else
3699 filter->dlist[direct].alist = NULL;
3700 }
3701 }
3702 }
3703 }
3704}
3705
3706/* Set prefix list to the peer. */
3707int
3708peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003709 const char *name)
paul718e3742002-12-13 20:15:29 +00003710{
3711 struct bgp_filter *filter;
3712 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003713 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003714
3715 if (! peer->afc[afi][safi])
3716 return BGP_ERR_PEER_INACTIVE;
3717
3718 if (direct != FILTER_IN && direct != FILTER_OUT)
3719 return BGP_ERR_INVALID_VALUE;
3720
3721 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3722 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3723
3724 filter = &peer->filter[afi][safi];
3725
3726 if (filter->dlist[direct].name)
3727 return BGP_ERR_PEER_FILTER_CONFLICT;
3728
3729 if (filter->plist[direct].name)
3730 free (filter->plist[direct].name);
3731 filter->plist[direct].name = strdup (name);
3732 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3733
3734 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3735 return 0;
3736
3737 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003738 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003739 {
3740 filter = &peer->filter[afi][safi];
3741
3742 if (! peer->af_group[afi][safi])
3743 continue;
3744
3745 if (filter->plist[direct].name)
3746 free (filter->plist[direct].name);
3747 filter->plist[direct].name = strdup (name);
3748 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3749 }
3750 return 0;
3751}
3752
3753int
3754peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3755{
3756 struct bgp_filter *filter;
3757 struct bgp_filter *gfilter;
3758 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003759 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003760
3761 if (! peer->afc[afi][safi])
3762 return BGP_ERR_PEER_INACTIVE;
3763
3764 if (direct != FILTER_IN && direct != FILTER_OUT)
3765 return BGP_ERR_INVALID_VALUE;
3766
3767 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3768 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3769
3770 filter = &peer->filter[afi][safi];
3771
3772 /* apply peer-group filter */
3773 if (peer->af_group[afi][safi])
3774 {
3775 gfilter = &peer->group->conf->filter[afi][safi];
3776
3777 if (gfilter->plist[direct].name)
3778 {
3779 if (filter->plist[direct].name)
3780 free (filter->plist[direct].name);
3781 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3782 filter->plist[direct].plist = gfilter->plist[direct].plist;
3783 return 0;
3784 }
3785 }
3786
3787 if (filter->plist[direct].name)
3788 free (filter->plist[direct].name);
3789 filter->plist[direct].name = NULL;
3790 filter->plist[direct].plist = NULL;
3791
3792 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3793 return 0;
3794
3795 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003796 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003797 {
3798 filter = &peer->filter[afi][safi];
3799
3800 if (! peer->af_group[afi][safi])
3801 continue;
3802
3803 if (filter->plist[direct].name)
3804 free (filter->plist[direct].name);
3805 filter->plist[direct].name = NULL;
3806 filter->plist[direct].plist = NULL;
3807 }
3808
3809 return 0;
3810}
3811
3812/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003813static void
paul718e3742002-12-13 20:15:29 +00003814peer_prefix_list_update (struct prefix_list *plist)
3815{
paul1eb8ef22005-04-07 07:30:20 +00003816 struct listnode *mnode, *mnnode;
3817 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003818 struct bgp *bgp;
3819 struct peer *peer;
3820 struct peer_group *group;
3821 struct bgp_filter *filter;
3822 afi_t afi;
3823 safi_t safi;
3824 int direct;
3825
paul1eb8ef22005-04-07 07:30:20 +00003826 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003827 {
paul1eb8ef22005-04-07 07:30:20 +00003828 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003829 {
3830 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3831 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3832 {
3833 filter = &peer->filter[afi][safi];
3834
3835 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3836 {
3837 if (filter->plist[direct].name)
3838 filter->plist[direct].plist =
3839 prefix_list_lookup (afi, filter->plist[direct].name);
3840 else
3841 filter->plist[direct].plist = NULL;
3842 }
3843 }
3844 }
paul1eb8ef22005-04-07 07:30:20 +00003845 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003846 {
3847 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3848 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3849 {
3850 filter = &group->conf->filter[afi][safi];
3851
3852 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3853 {
3854 if (filter->plist[direct].name)
3855 filter->plist[direct].plist =
3856 prefix_list_lookup (afi, filter->plist[direct].name);
3857 else
3858 filter->plist[direct].plist = NULL;
3859 }
3860 }
3861 }
3862 }
3863}
3864
3865int
3866peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003867 const char *name)
paul718e3742002-12-13 20:15:29 +00003868{
3869 struct bgp_filter *filter;
3870 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003871 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003872
3873 if (! peer->afc[afi][safi])
3874 return BGP_ERR_PEER_INACTIVE;
3875
3876 if (direct != FILTER_IN && direct != FILTER_OUT)
3877 return BGP_ERR_INVALID_VALUE;
3878
3879 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3880 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3881
3882 filter = &peer->filter[afi][safi];
3883
3884 if (filter->aslist[direct].name)
3885 free (filter->aslist[direct].name);
3886 filter->aslist[direct].name = strdup (name);
3887 filter->aslist[direct].aslist = as_list_lookup (name);
3888
3889 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3890 return 0;
3891
3892 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003893 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003894 {
3895 filter = &peer->filter[afi][safi];
3896
3897 if (! peer->af_group[afi][safi])
3898 continue;
3899
3900 if (filter->aslist[direct].name)
3901 free (filter->aslist[direct].name);
3902 filter->aslist[direct].name = strdup (name);
3903 filter->aslist[direct].aslist = as_list_lookup (name);
3904 }
3905 return 0;
3906}
3907
3908int
3909peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3910{
3911 struct bgp_filter *filter;
3912 struct bgp_filter *gfilter;
3913 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003915
3916 if (! peer->afc[afi][safi])
3917 return BGP_ERR_PEER_INACTIVE;
3918
hassob5f29602005-05-25 21:00:28 +00003919 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003920 return BGP_ERR_INVALID_VALUE;
3921
hassob5f29602005-05-25 21:00:28 +00003922 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003923 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3924
3925 filter = &peer->filter[afi][safi];
3926
3927 /* apply peer-group filter */
3928 if (peer->af_group[afi][safi])
3929 {
3930 gfilter = &peer->group->conf->filter[afi][safi];
3931
3932 if (gfilter->aslist[direct].name)
3933 {
3934 if (filter->aslist[direct].name)
3935 free (filter->aslist[direct].name);
3936 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3937 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3938 return 0;
3939 }
3940 }
3941
3942 if (filter->aslist[direct].name)
3943 free (filter->aslist[direct].name);
3944 filter->aslist[direct].name = NULL;
3945 filter->aslist[direct].aslist = NULL;
3946
3947 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3948 return 0;
3949
3950 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003951 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003952 {
3953 filter = &peer->filter[afi][safi];
3954
3955 if (! peer->af_group[afi][safi])
3956 continue;
3957
3958 if (filter->aslist[direct].name)
3959 free (filter->aslist[direct].name);
3960 filter->aslist[direct].name = NULL;
3961 filter->aslist[direct].aslist = NULL;
3962 }
3963
3964 return 0;
3965}
3966
paul94f2b392005-06-28 12:44:16 +00003967static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003968peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003969{
3970 afi_t afi;
3971 safi_t safi;
3972 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003973 struct listnode *mnode, *mnnode;
3974 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003975 struct bgp *bgp;
3976 struct peer *peer;
3977 struct peer_group *group;
3978 struct bgp_filter *filter;
3979
paul1eb8ef22005-04-07 07:30:20 +00003980 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003981 {
paul1eb8ef22005-04-07 07:30:20 +00003982 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003983 {
3984 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3985 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3986 {
3987 filter = &peer->filter[afi][safi];
3988
3989 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3990 {
3991 if (filter->aslist[direct].name)
3992 filter->aslist[direct].aslist =
3993 as_list_lookup (filter->aslist[direct].name);
3994 else
3995 filter->aslist[direct].aslist = NULL;
3996 }
3997 }
3998 }
paul1eb8ef22005-04-07 07:30:20 +00003999 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004000 {
4001 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4002 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4003 {
4004 filter = &group->conf->filter[afi][safi];
4005
4006 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4007 {
4008 if (filter->aslist[direct].name)
4009 filter->aslist[direct].aslist =
4010 as_list_lookup (filter->aslist[direct].name);
4011 else
4012 filter->aslist[direct].aslist = NULL;
4013 }
4014 }
4015 }
4016 }
4017}
4018
4019/* Set route-map to the peer. */
4020int
4021peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004022 const char *name)
paul718e3742002-12-13 20:15:29 +00004023{
4024 struct bgp_filter *filter;
4025 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004026 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004027
4028 if (! peer->afc[afi][safi])
4029 return BGP_ERR_PEER_INACTIVE;
4030
paulfee0f4c2004-09-13 05:12:46 +00004031 if (direct != RMAP_IN && direct != RMAP_OUT &&
4032 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004033 return BGP_ERR_INVALID_VALUE;
4034
paulfee0f4c2004-09-13 05:12:46 +00004035 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4036 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004037 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4038
4039 filter = &peer->filter[afi][safi];
4040
4041 if (filter->map[direct].name)
4042 free (filter->map[direct].name);
4043
4044 filter->map[direct].name = strdup (name);
4045 filter->map[direct].map = route_map_lookup_by_name (name);
4046
4047 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4048 return 0;
4049
4050 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004051 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004052 {
4053 filter = &peer->filter[afi][safi];
4054
4055 if (! peer->af_group[afi][safi])
4056 continue;
4057
4058 if (filter->map[direct].name)
4059 free (filter->map[direct].name);
4060 filter->map[direct].name = strdup (name);
4061 filter->map[direct].map = route_map_lookup_by_name (name);
4062 }
4063 return 0;
4064}
4065
4066/* Unset route-map from the peer. */
4067int
4068peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4069{
4070 struct bgp_filter *filter;
4071 struct bgp_filter *gfilter;
4072 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004073 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004074
4075 if (! peer->afc[afi][safi])
4076 return BGP_ERR_PEER_INACTIVE;
4077
hassob5f29602005-05-25 21:00:28 +00004078 if (direct != RMAP_IN && direct != RMAP_OUT &&
4079 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004080 return BGP_ERR_INVALID_VALUE;
4081
hassob5f29602005-05-25 21:00:28 +00004082 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4083 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004084 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4085
4086 filter = &peer->filter[afi][safi];
4087
4088 /* apply peer-group filter */
4089 if (peer->af_group[afi][safi])
4090 {
4091 gfilter = &peer->group->conf->filter[afi][safi];
4092
4093 if (gfilter->map[direct].name)
4094 {
4095 if (filter->map[direct].name)
4096 free (filter->map[direct].name);
4097 filter->map[direct].name = strdup (gfilter->map[direct].name);
4098 filter->map[direct].map = gfilter->map[direct].map;
4099 return 0;
4100 }
4101 }
4102
4103 if (filter->map[direct].name)
4104 free (filter->map[direct].name);
4105 filter->map[direct].name = NULL;
4106 filter->map[direct].map = NULL;
4107
4108 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4109 return 0;
4110
4111 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004112 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004113 {
4114 filter = &peer->filter[afi][safi];
4115
4116 if (! peer->af_group[afi][safi])
4117 continue;
4118
4119 if (filter->map[direct].name)
4120 free (filter->map[direct].name);
4121 filter->map[direct].name = NULL;
4122 filter->map[direct].map = NULL;
4123 }
4124 return 0;
4125}
4126
4127/* Set unsuppress-map to the peer. */
4128int
paulfd79ac92004-10-13 05:06:08 +00004129peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4130 const char *name)
paul718e3742002-12-13 20:15:29 +00004131{
4132 struct bgp_filter *filter;
4133 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004134 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004135
4136 if (! peer->afc[afi][safi])
4137 return BGP_ERR_PEER_INACTIVE;
4138
4139 if (peer_is_group_member (peer, afi, safi))
4140 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4141
4142 filter = &peer->filter[afi][safi];
4143
4144 if (filter->usmap.name)
4145 free (filter->usmap.name);
4146
4147 filter->usmap.name = strdup (name);
4148 filter->usmap.map = route_map_lookup_by_name (name);
4149
4150 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4151 return 0;
4152
4153 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004154 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004155 {
4156 filter = &peer->filter[afi][safi];
4157
4158 if (! peer->af_group[afi][safi])
4159 continue;
4160
4161 if (filter->usmap.name)
4162 free (filter->usmap.name);
4163 filter->usmap.name = strdup (name);
4164 filter->usmap.map = route_map_lookup_by_name (name);
4165 }
4166 return 0;
4167}
4168
4169/* Unset route-map from the peer. */
4170int
4171peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4172{
4173 struct bgp_filter *filter;
4174 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004175 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004176
4177 if (! peer->afc[afi][safi])
4178 return BGP_ERR_PEER_INACTIVE;
4179
4180 if (peer_is_group_member (peer, afi, safi))
4181 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4182
4183 filter = &peer->filter[afi][safi];
4184
4185 if (filter->usmap.name)
4186 free (filter->usmap.name);
4187 filter->usmap.name = NULL;
4188 filter->usmap.map = NULL;
4189
4190 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4191 return 0;
4192
4193 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004194 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004195 {
4196 filter = &peer->filter[afi][safi];
4197
4198 if (! peer->af_group[afi][safi])
4199 continue;
4200
4201 if (filter->usmap.name)
4202 free (filter->usmap.name);
4203 filter->usmap.name = NULL;
4204 filter->usmap.map = NULL;
4205 }
4206 return 0;
4207}
4208
4209int
4210peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004211 u_int32_t max, u_char threshold,
4212 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004213{
4214 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004215 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004216
4217 if (! peer->afc[afi][safi])
4218 return BGP_ERR_PEER_INACTIVE;
4219
4220 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4221 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004222 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004223 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004224 if (warning)
4225 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4226 else
4227 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4228
4229 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4230 return 0;
4231
4232 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004233 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004234 {
4235 if (! peer->af_group[afi][safi])
4236 continue;
4237
4238 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4239 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004240 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004241 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004242 if (warning)
4243 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4244 else
4245 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4246 }
4247 return 0;
4248}
4249
4250int
4251peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4252{
4253 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004254 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004255
4256 if (! peer->afc[afi][safi])
4257 return BGP_ERR_PEER_INACTIVE;
4258
4259 /* apply peer-group config */
4260 if (peer->af_group[afi][safi])
4261 {
4262 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4263 PEER_FLAG_MAX_PREFIX))
4264 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4265 else
4266 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4267
4268 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4269 PEER_FLAG_MAX_PREFIX_WARNING))
4270 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4271 else
4272 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4273
4274 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004275 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004276 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004277 return 0;
4278 }
4279
4280 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4281 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4282 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004283 peer->pmax_threshold[afi][safi] = 0;
4284 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004285
4286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4287 return 0;
4288
4289 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004290 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004291 {
4292 if (! peer->af_group[afi][safi])
4293 continue;
4294
4295 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4296 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4297 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004298 peer->pmax_threshold[afi][safi] = 0;
4299 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004300 }
4301 return 0;
4302}
4303
4304int
4305peer_clear (struct peer *peer)
4306{
4307 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4308 {
hasso0a486e52005-02-01 20:57:17 +00004309 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4310 {
4311 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4312 if (peer->t_pmax_restart)
4313 {
4314 BGP_TIMER_OFF (peer->t_pmax_restart);
4315 if (BGP_DEBUG (events, EVENTS))
4316 zlog_debug ("%s Maximum-prefix restart timer canceled",
4317 peer->host);
4318 }
4319 BGP_EVENT_ADD (peer, BGP_Start);
4320 return 0;
4321 }
4322
paul718e3742002-12-13 20:15:29 +00004323 peer->v_start = BGP_INIT_START_TIMER;
4324 if (peer->status == Established)
4325 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4326 BGP_NOTIFY_CEASE_ADMIN_RESET);
4327 else
4328 BGP_EVENT_ADD (peer, BGP_Stop);
4329 }
4330 return 0;
4331}
4332
4333int
4334peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4335 enum bgp_clear_type stype)
4336{
4337 if (peer->status != Established)
4338 return 0;
4339
4340 if (! peer->afc[afi][safi])
4341 return BGP_ERR_AF_UNCONFIGURED;
4342
paulfee0f4c2004-09-13 05:12:46 +00004343 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4344 {
4345 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4346 return 0;
4347 bgp_check_local_routes_rsclient (peer, afi, safi);
4348 bgp_soft_reconfig_rsclient (peer, afi, safi);
4349 }
4350
paul718e3742002-12-13 20:15:29 +00004351 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4352 bgp_announce_route (peer, afi, safi);
4353
4354 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4355 {
4356 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4357 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4358 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4359 {
4360 struct bgp_filter *filter = &peer->filter[afi][safi];
4361 u_char prefix_type;
4362
4363 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4364 prefix_type = ORF_TYPE_PREFIX;
4365 else
4366 prefix_type = ORF_TYPE_PREFIX_OLD;
4367
4368 if (filter->plist[FILTER_IN].plist)
4369 {
4370 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4371 bgp_route_refresh_send (peer, afi, safi,
4372 prefix_type, REFRESH_DEFER, 1);
4373 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4374 REFRESH_IMMEDIATE, 0);
4375 }
4376 else
4377 {
4378 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4379 bgp_route_refresh_send (peer, afi, safi,
4380 prefix_type, REFRESH_IMMEDIATE, 1);
4381 else
4382 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4383 }
4384 return 0;
4385 }
4386 }
4387
4388 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4389 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4390 {
4391 /* If neighbor has soft reconfiguration inbound flag.
4392 Use Adj-RIB-In database. */
4393 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4394 bgp_soft_reconfig_in (peer, afi, safi);
4395 else
4396 {
4397 /* If neighbor has route refresh capability, send route refresh
4398 message to the peer. */
4399 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4400 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4401 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4402 else
4403 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4404 }
4405 }
4406 return 0;
4407}
4408
paulfd79ac92004-10-13 05:06:08 +00004409/* Display peer uptime.*/
4410/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004411char *
4412peer_uptime (time_t uptime2, char *buf, size_t len)
4413{
4414 time_t uptime1;
4415 struct tm *tm;
4416
4417 /* Check buffer length. */
4418 if (len < BGP_UPTIME_LEN)
4419 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004420 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004421 /* XXX: should return status instead of buf... */
4422 snprintf (buf, len, "<error> ");
4423 return buf;
paul718e3742002-12-13 20:15:29 +00004424 }
4425
4426 /* If there is no connection has been done before print `never'. */
4427 if (uptime2 == 0)
4428 {
4429 snprintf (buf, len, "never ");
4430 return buf;
4431 }
4432
4433 /* Get current time. */
4434 uptime1 = time (NULL);
4435 uptime1 -= uptime2;
4436 tm = gmtime (&uptime1);
4437
4438 /* Making formatted timer strings. */
4439#define ONE_DAY_SECOND 60*60*24
4440#define ONE_WEEK_SECOND 60*60*24*7
4441
4442 if (uptime1 < ONE_DAY_SECOND)
4443 snprintf (buf, len, "%02d:%02d:%02d",
4444 tm->tm_hour, tm->tm_min, tm->tm_sec);
4445 else if (uptime1 < ONE_WEEK_SECOND)
4446 snprintf (buf, len, "%dd%02dh%02dm",
4447 tm->tm_yday, tm->tm_hour, tm->tm_min);
4448 else
4449 snprintf (buf, len, "%02dw%dd%02dh",
4450 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4451 return buf;
4452}
4453
paul94f2b392005-06-28 12:44:16 +00004454static void
paul718e3742002-12-13 20:15:29 +00004455bgp_config_write_filter (struct vty *vty, struct peer *peer,
4456 afi_t afi, safi_t safi)
4457{
4458 struct bgp_filter *filter;
4459 struct bgp_filter *gfilter = NULL;
4460 char *addr;
4461 int in = FILTER_IN;
4462 int out = FILTER_OUT;
4463
4464 addr = peer->host;
4465 filter = &peer->filter[afi][safi];
4466 if (peer->af_group[afi][safi])
4467 gfilter = &peer->group->conf->filter[afi][safi];
4468
4469 /* distribute-list. */
4470 if (filter->dlist[in].name)
4471 if (! gfilter || ! gfilter->dlist[in].name
4472 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4473 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4474 filter->dlist[in].name, VTY_NEWLINE);
4475 if (filter->dlist[out].name && ! gfilter)
4476 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4477 filter->dlist[out].name, VTY_NEWLINE);
4478
4479 /* prefix-list. */
4480 if (filter->plist[in].name)
4481 if (! gfilter || ! gfilter->plist[in].name
4482 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4483 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4484 filter->plist[in].name, VTY_NEWLINE);
4485 if (filter->plist[out].name && ! gfilter)
4486 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4487 filter->plist[out].name, VTY_NEWLINE);
4488
4489 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004490 if (filter->map[RMAP_IN].name)
4491 if (! gfilter || ! gfilter->map[RMAP_IN].name
4492 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004493 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004494 filter->map[RMAP_IN].name, VTY_NEWLINE);
4495 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004496 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004497 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4498 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4499 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4500 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4501 if (filter->map[RMAP_EXPORT].name)
4502 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4503 || strcmp (filter->map[RMAP_EXPORT].name,
4504 gfilter->map[RMAP_EXPORT].name) != 0)
4505 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4506 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004507
4508 /* unsuppress-map */
4509 if (filter->usmap.name && ! gfilter)
4510 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4511 filter->usmap.name, VTY_NEWLINE);
4512
4513 /* filter-list. */
4514 if (filter->aslist[in].name)
4515 if (! gfilter || ! gfilter->aslist[in].name
4516 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4517 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4518 filter->aslist[in].name, VTY_NEWLINE);
4519 if (filter->aslist[out].name && ! gfilter)
4520 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4521 filter->aslist[out].name, VTY_NEWLINE);
4522}
4523
4524/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004525static void
paul718e3742002-12-13 20:15:29 +00004526bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4527 struct peer *peer, afi_t afi, safi_t safi)
4528{
4529 struct bgp_filter *filter;
4530 struct peer *g_peer = NULL;
4531 char buf[SU_ADDRSTRLEN];
4532 char *addr;
4533
4534 filter = &peer->filter[afi][safi];
4535 addr = peer->host;
4536 if (peer_group_active (peer))
4537 g_peer = peer->group->conf;
4538
4539 /************************************
4540 ****** Global to the neighbor ******
4541 ************************************/
4542 if (afi == AFI_IP && safi == SAFI_UNICAST)
4543 {
4544 /* remote-as. */
4545 if (! peer_group_active (peer))
4546 {
4547 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4548 vty_out (vty, " neighbor %s peer-group%s", addr,
4549 VTY_NEWLINE);
4550 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004551 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004552 VTY_NEWLINE);
4553 }
4554 else
4555 {
4556 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004557 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004558 VTY_NEWLINE);
4559 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4560 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4561 peer->group->name, VTY_NEWLINE);
4562 }
4563
4564 /* local-as. */
4565 if (peer->change_local_as)
4566 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004567 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004568 peer->change_local_as,
4569 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4570 " no-prepend" : "", VTY_NEWLINE);
4571
4572 /* Description. */
4573 if (peer->desc)
4574 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4575 VTY_NEWLINE);
4576
4577 /* Shutdown. */
4578 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4579 if (! peer_group_active (peer) ||
4580 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4581 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4582
Paul Jakma0df7c912008-07-21 21:02:49 +00004583 /* Password. */
4584 if (peer->password)
4585 if (!peer_group_active (peer)
4586 || ! g_peer->password
4587 || strcmp (peer->password, g_peer->password) != 0)
4588 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4589 VTY_NEWLINE);
4590
paul718e3742002-12-13 20:15:29 +00004591 /* BGP port. */
4592 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004593 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004594 VTY_NEWLINE);
4595
4596 /* Local interface name. */
4597 if (peer->ifname)
4598 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4599 VTY_NEWLINE);
4600
4601 /* Passive. */
4602 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4603 if (! peer_group_active (peer) ||
4604 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4605 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4606
4607 /* EBGP multihop. */
4608 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4609 if (! peer_group_active (peer) ||
4610 g_peer->ttl != peer->ttl)
4611 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4612 VTY_NEWLINE);
4613
hasso6ffd2072005-02-02 14:50:11 +00004614 /* disable-connected-check. */
4615 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004616 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004617 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4618 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004619
4620 /* Update-source. */
4621 if (peer->update_if)
4622 if (! peer_group_active (peer) || ! g_peer->update_if
4623 || strcmp (g_peer->update_if, peer->update_if) != 0)
4624 vty_out (vty, " neighbor %s update-source %s%s", addr,
4625 peer->update_if, VTY_NEWLINE);
4626 if (peer->update_source)
4627 if (! peer_group_active (peer) || ! g_peer->update_source
4628 || sockunion_cmp (g_peer->update_source,
4629 peer->update_source) != 0)
4630 vty_out (vty, " neighbor %s update-source %s%s", addr,
4631 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4632 VTY_NEWLINE);
4633
paul718e3742002-12-13 20:15:29 +00004634 /* advertisement-interval */
4635 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4636 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4637 addr, peer->v_routeadv, VTY_NEWLINE);
4638
4639 /* timers. */
4640 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4641 && ! peer_group_active (peer))
4642 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4643 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4644
4645 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4646 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4647 peer->connect, VTY_NEWLINE);
4648
4649 /* Default weight. */
4650 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4651 if (! peer_group_active (peer) ||
4652 g_peer->weight != peer->weight)
4653 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4654 VTY_NEWLINE);
4655
paul718e3742002-12-13 20:15:29 +00004656 /* Dynamic capability. */
4657 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4658 if (! peer_group_active (peer) ||
4659 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4660 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4661 VTY_NEWLINE);
4662
4663 /* dont capability negotiation. */
4664 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4665 if (! peer_group_active (peer) ||
4666 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4667 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4668 VTY_NEWLINE);
4669
4670 /* override capability negotiation. */
4671 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4672 if (! peer_group_active (peer) ||
4673 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4674 vty_out (vty, " neighbor %s override-capability%s", addr,
4675 VTY_NEWLINE);
4676
4677 /* strict capability negotiation. */
4678 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4679 if (! peer_group_active (peer) ||
4680 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4681 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4682 VTY_NEWLINE);
4683
4684 if (! peer_group_active (peer))
4685 {
4686 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4687 {
4688 if (peer->afc[AFI_IP][SAFI_UNICAST])
4689 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4690 }
4691 else
4692 {
4693 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4694 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4695 }
4696 }
4697 }
4698
4699
4700 /************************************
4701 ****** Per AF to the neighbor ******
4702 ************************************/
4703
4704 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4705 {
4706 if (peer->af_group[afi][safi])
4707 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4708 peer->group->name, VTY_NEWLINE);
4709 else
4710 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4711 }
4712
4713 /* ORF capability. */
4714 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4715 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4716 if (! peer->af_group[afi][safi])
4717 {
4718 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4719
4720 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4721 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4722 vty_out (vty, " both");
4723 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4724 vty_out (vty, " send");
4725 else
4726 vty_out (vty, " receive");
4727 vty_out (vty, "%s", VTY_NEWLINE);
4728 }
4729
4730 /* Route reflector client. */
4731 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4732 && ! peer->af_group[afi][safi])
4733 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4734 VTY_NEWLINE);
4735
4736 /* Nexthop self. */
4737 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4738 && ! peer->af_group[afi][safi])
4739 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4740
4741 /* Remove private AS. */
4742 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4743 && ! peer->af_group[afi][safi])
4744 vty_out (vty, " neighbor %s remove-private-AS%s",
4745 addr, VTY_NEWLINE);
4746
4747 /* send-community print. */
4748 if (! peer->af_group[afi][safi])
4749 {
4750 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4751 {
4752 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4753 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4754 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4755 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4756 vty_out (vty, " neighbor %s send-community extended%s",
4757 addr, VTY_NEWLINE);
4758 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4759 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4760 }
4761 else
4762 {
4763 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4764 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4765 vty_out (vty, " no neighbor %s send-community both%s",
4766 addr, VTY_NEWLINE);
4767 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4768 vty_out (vty, " no neighbor %s send-community extended%s",
4769 addr, VTY_NEWLINE);
4770 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4771 vty_out (vty, " no neighbor %s send-community%s",
4772 addr, VTY_NEWLINE);
4773 }
4774 }
4775
4776 /* Default information */
4777 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4778 && ! peer->af_group[afi][safi])
4779 {
4780 vty_out (vty, " neighbor %s default-originate", addr);
4781 if (peer->default_rmap[afi][safi].name)
4782 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4783 vty_out (vty, "%s", VTY_NEWLINE);
4784 }
4785
4786 /* Soft reconfiguration inbound. */
4787 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4788 if (! peer->af_group[afi][safi] ||
4789 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4790 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4791 VTY_NEWLINE);
4792
4793 /* maximum-prefix. */
4794 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4795 if (! peer->af_group[afi][safi]
4796 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004797 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004798 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4799 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004800 {
hasso0a486e52005-02-01 20:57:17 +00004801 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4802 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4803 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4804 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4805 vty_out (vty, " warning-only");
4806 if (peer->pmax_restart[afi][safi])
4807 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4808 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004809 }
paul718e3742002-12-13 20:15:29 +00004810
4811 /* Route server client. */
4812 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4813 && ! peer->af_group[afi][safi])
4814 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4815
4816 /* Allow AS in. */
4817 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4818 if (! peer_group_active (peer)
4819 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4820 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4821 {
4822 if (peer->allowas_in[afi][safi] == 3)
4823 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4824 else
4825 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4826 peer->allowas_in[afi][safi], VTY_NEWLINE);
4827 }
4828
4829 /* Filter. */
4830 bgp_config_write_filter (vty, peer, afi, safi);
4831
4832 /* atribute-unchanged. */
4833 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4834 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4835 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4836 && ! peer->af_group[afi][safi])
4837 {
4838 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4839 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4840 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4841 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4842 else
4843 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4844 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4845 " as-path" : "",
4846 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4847 " next-hop" : "",
4848 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4849 " med" : "", VTY_NEWLINE);
4850 }
4851}
4852
4853/* Display "address-family" configuration header. */
4854void
4855bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4856 int *write)
4857{
4858 if (*write)
4859 return;
4860
4861 if (afi == AFI_IP && safi == SAFI_UNICAST)
4862 return;
4863
4864 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4865
4866 if (afi == AFI_IP)
4867 {
4868 if (safi == SAFI_MULTICAST)
4869 vty_out (vty, "ipv4 multicast");
4870 else if (safi == SAFI_MPLS_VPN)
4871 vty_out (vty, "vpnv4 unicast");
4872 }
4873 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004874 {
4875 vty_out (vty, "ipv6");
4876
4877 if (safi == SAFI_MULTICAST)
4878 vty_out (vty, " multicast");
4879 }
paul718e3742002-12-13 20:15:29 +00004880
4881 vty_out (vty, "%s", VTY_NEWLINE);
4882
4883 *write = 1;
4884}
4885
4886/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004887static int
paul718e3742002-12-13 20:15:29 +00004888bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4889 safi_t safi)
4890{
4891 int write = 0;
4892 struct peer *peer;
4893 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004894 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004895
4896 bgp_config_write_network (vty, bgp, afi, safi, &write);
4897
4898 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4899
paul1eb8ef22005-04-07 07:30:20 +00004900 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004901 {
4902 if (group->conf->afc[afi][safi])
4903 {
4904 bgp_config_write_family_header (vty, afi, safi, &write);
4905 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4906 }
4907 }
paul1eb8ef22005-04-07 07:30:20 +00004908 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004909 {
4910 if (peer->afc[afi][safi])
4911 {
4912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4913 {
4914 bgp_config_write_family_header (vty, afi, safi, &write);
4915 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4916 }
4917 }
4918 }
4919 if (write)
4920 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4921
4922 return write;
4923}
4924
4925int
4926bgp_config_write (struct vty *vty)
4927{
4928 int write = 0;
4929 struct bgp *bgp;
4930 struct peer_group *group;
4931 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004932 struct listnode *node, *nnode;
4933 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004934
4935 /* BGP Multiple instance. */
4936 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4937 {
4938 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4939 write++;
4940 }
4941
4942 /* BGP Config type. */
4943 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4944 {
4945 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4946 write++;
4947 }
4948
4949 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004950 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004951 {
4952 if (write)
4953 vty_out (vty, "!%s", VTY_NEWLINE);
4954
4955 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004956 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004957
4958 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4959 {
4960 if (bgp->name)
4961 vty_out (vty, " view %s", bgp->name);
4962 }
4963 vty_out (vty, "%s", VTY_NEWLINE);
4964
4965 /* No Synchronization */
4966 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4967 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4968
4969 /* BGP fast-external-failover. */
4970 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4971 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4972
4973 /* BGP router ID. */
4974 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4975 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4976 VTY_NEWLINE);
4977
paul848973c2003-08-13 00:32:49 +00004978 /* BGP log-neighbor-changes. */
4979 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4980 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4981
paul718e3742002-12-13 20:15:29 +00004982 /* BGP configuration. */
4983 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4984 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4985
4986 /* BGP default ipv4-unicast. */
4987 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4988 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4989
4990 /* BGP default local-preference. */
4991 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4992 vty_out (vty, " bgp default local-preference %d%s",
4993 bgp->default_local_pref, VTY_NEWLINE);
4994
4995 /* BGP client-to-client reflection. */
4996 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4997 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4998
4999 /* BGP cluster ID. */
5000 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5001 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5002 VTY_NEWLINE);
5003
hassoe0701b72004-05-20 09:19:34 +00005004 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005005 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005006 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5007 VTY_NEWLINE);
5008
5009 /* Confederation peer */
5010 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005011 {
hassoe0701b72004-05-20 09:19:34 +00005012 int i;
paul718e3742002-12-13 20:15:29 +00005013
hassoe0701b72004-05-20 09:19:34 +00005014 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005015
hassoe0701b72004-05-20 09:19:34 +00005016 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005017 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005018
hassoe0701b72004-05-20 09:19:34 +00005019 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005020 }
5021
5022 /* BGP enforce-first-as. */
5023 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5024 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5025
5026 /* BGP deterministic-med. */
5027 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5028 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005029
5030 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005031 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5032 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5033 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005034 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5035 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5036
paul718e3742002-12-13 20:15:29 +00005037 /* BGP bestpath method. */
5038 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5039 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005040 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5041 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005042 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5043 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5044 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5045 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5046 {
5047 vty_out (vty, " bgp bestpath med");
5048 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5049 vty_out (vty, " confed");
5050 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5051 vty_out (vty, " missing-as-worst");
5052 vty_out (vty, "%s", VTY_NEWLINE);
5053 }
5054
5055 /* BGP network import check. */
5056 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5057 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5058
5059 /* BGP scan interval. */
5060 bgp_config_write_scan_time (vty);
5061
5062 /* BGP flag dampening. */
5063 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5064 BGP_CONFIG_DAMPENING))
5065 bgp_config_write_damp (vty);
5066
5067 /* BGP static route configuration. */
5068 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5069
5070 /* BGP redistribute configuration. */
5071 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5072
5073 /* BGP timers configuration. */
5074 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5075 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5076 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5077 bgp->default_holdtime, VTY_NEWLINE);
5078
5079 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005080 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005081 {
5082 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5083 }
5084
5085 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005086 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005087 {
5088 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5089 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5090 }
5091
5092 /* Distance configuration. */
5093 bgp_config_write_distance (vty, bgp);
5094
5095 /* No auto-summary */
5096 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5097 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5098
5099 /* IPv4 multicast configuration. */
5100 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5101
5102 /* IPv4 VPN configuration. */
5103 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5104
5105 /* IPv6 unicast configuration. */
5106 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5107
Paul Jakma37a217a2007-04-10 19:20:29 +00005108 /* IPv6 multicast configuration. */
5109 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5110
paul718e3742002-12-13 20:15:29 +00005111 write++;
5112 }
5113 return write;
5114}
5115
5116void
paul94f2b392005-06-28 12:44:16 +00005117bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005118{
5119 memset (&bgp_master, 0, sizeof (struct bgp_master));
5120
5121 bm = &bgp_master;
5122 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005123 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005124 bm->port = BGP_PORT_DEFAULT;
5125 bm->master = thread_master_create ();
5126 bm->start_time = time (NULL);
5127}
paul200df112005-06-01 11:17:05 +00005128
paul718e3742002-12-13 20:15:29 +00005129
5130void
paul94f2b392005-06-28 12:44:16 +00005131bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005132{
paul718e3742002-12-13 20:15:29 +00005133 /* BGP VTY commands installation. */
5134 bgp_vty_init ();
5135
5136 /* Create BGP server socket. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +00005137 bgp_socket (NULL, bm->port, bm->address);
paul718e3742002-12-13 20:15:29 +00005138
5139 /* Init zebra. */
5140 bgp_zebra_init ();
5141
5142 /* BGP inits. */
5143 bgp_attr_init ();
5144 bgp_debug_init ();
5145 bgp_dump_init ();
5146 bgp_route_init ();
5147 bgp_route_map_init ();
5148 bgp_scan_init ();
5149 bgp_mplsvpn_init ();
5150
5151 /* Access list initialize. */
5152 access_list_init ();
5153 access_list_add_hook (peer_distribute_update);
5154 access_list_delete_hook (peer_distribute_update);
5155
5156 /* Filter list initialize. */
5157 bgp_filter_init ();
5158 as_list_add_hook (peer_aslist_update);
5159 as_list_delete_hook (peer_aslist_update);
5160
5161 /* Prefix list initialize.*/
5162 prefix_list_init ();
5163 prefix_list_add_hook (peer_prefix_list_update);
5164 prefix_list_delete_hook (peer_prefix_list_update);
5165
5166 /* Community list initialize. */
5167 bgp_clist = community_list_init ();
5168
5169#ifdef HAVE_SNMP
5170 bgp_snmp_init ();
5171#endif /* HAVE_SNMP */
5172}
paul545acaf2004-04-20 15:13:15 +00005173
5174void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005175bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005176{
paul545acaf2004-04-20 15:13:15 +00005177 struct bgp *bgp;
5178 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005179 struct listnode *node, *nnode;
5180 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005181
paul1eb8ef22005-04-07 07:30:20 +00005182 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5183 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005184 if (peer->status == Established)
5185 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5186 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005187
paul545acaf2004-04-20 15:13:15 +00005188 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005189
paule210cf92005-06-15 19:15:35 +00005190 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005191 {
5192 work_queue_free (bm->process_main_queue);
5193 bm->process_main_queue = NULL;
5194 }
paule210cf92005-06-15 19:15:35 +00005195 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005196 {
5197 work_queue_free (bm->process_rsclient_queue);
5198 bm->process_rsclient_queue = NULL;
5199 }
paul545acaf2004-04-20 15:13:15 +00005200}