blob: 1fefbd3f5d1b2dd607b4ffd624ee399d16be84d2 [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 }
2076
2077 bgp_unlock(bgp); /* initial reference */
2078
2079 return 0;
2080}
2081
2082static void bgp_free (struct bgp *);
2083
2084void
2085bgp_lock (struct bgp *bgp)
2086{
2087 ++bgp->lock;
2088}
2089
2090void
2091bgp_unlock(struct bgp *bgp)
2092{
2093 if (--bgp->lock == 0)
2094 bgp_free (bgp);
2095}
2096
2097static void
2098bgp_free (struct bgp *bgp)
2099{
2100 afi_t afi;
2101 safi_t safi;
2102
2103 list_delete (bgp->group);
2104 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002105 list_delete (bgp->rsclient);
2106
paul718e3742002-12-13 20:15:29 +00002107 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002108
paul718e3742002-12-13 20:15:29 +00002109 if (bgp->name)
2110 free (bgp->name);
2111
2112 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2113 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2114 {
2115 if (bgp->route[afi][safi])
2116 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2117 if (bgp->aggregate[afi][safi])
2118 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2119 if (bgp->rib[afi][safi])
2120 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2121 }
2122 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002123}
2124
2125struct peer *
2126peer_lookup (struct bgp *bgp, union sockunion *su)
2127{
2128 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002129 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002130
2131 if (! bgp)
2132 bgp = bgp_get_default ();
2133
2134 if (! bgp)
2135 return NULL;
2136
paul1eb8ef22005-04-07 07:30:20 +00002137 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002138 {
pauleb821182004-05-01 08:44:08 +00002139 if (sockunion_same (&peer->su, su)
2140 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2141 return peer;
paul718e3742002-12-13 20:15:29 +00002142 }
2143 return NULL;
2144}
2145
2146struct peer *
2147peer_lookup_with_open (union sockunion *su, as_t remote_as,
2148 struct in_addr *remote_id, int *as)
2149{
2150 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002151 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002152 struct bgp *bgp;
2153
2154 bgp = bgp_get_default ();
2155 if (! bgp)
2156 return NULL;
2157
paul1eb8ef22005-04-07 07:30:20 +00002158 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002159 {
pauleb821182004-05-01 08:44:08 +00002160 if (sockunion_same (&peer->su, su)
2161 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2162 {
2163 if (peer->as == remote_as
2164 && peer->remote_id.s_addr == remote_id->s_addr)
2165 return peer;
2166 if (peer->as == remote_as)
2167 *as = 1;
2168 }
paul718e3742002-12-13 20:15:29 +00002169 }
paul1eb8ef22005-04-07 07:30:20 +00002170 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002171 {
pauleb821182004-05-01 08:44:08 +00002172 if (sockunion_same (&peer->su, su)
2173 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2174 {
2175 if (peer->as == remote_as
2176 && peer->remote_id.s_addr == 0)
2177 return peer;
2178 if (peer->as == remote_as)
2179 *as = 1;
2180 }
paul718e3742002-12-13 20:15:29 +00002181 }
2182 return NULL;
2183}
2184
2185/* If peer is configured at least one address family return 1. */
2186int
2187peer_active (struct peer *peer)
2188{
2189 if (peer->afc[AFI_IP][SAFI_UNICAST]
2190 || peer->afc[AFI_IP][SAFI_MULTICAST]
2191 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2192 || peer->afc[AFI_IP6][SAFI_UNICAST]
2193 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2194 return 1;
2195 return 0;
2196}
2197
2198/* If peer is negotiated at least one address family return 1. */
2199int
2200peer_active_nego (struct peer *peer)
2201{
2202 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2203 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2204 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2205 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2206 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2207 return 1;
2208 return 0;
2209}
2210
2211/* peer_flag_change_type. */
2212enum peer_change_type
2213{
2214 peer_change_none,
2215 peer_change_reset,
2216 peer_change_reset_in,
2217 peer_change_reset_out,
2218};
2219
paul94f2b392005-06-28 12:44:16 +00002220static void
paul718e3742002-12-13 20:15:29 +00002221peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2222 enum peer_change_type type)
2223{
2224 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2225 return;
2226
2227 if (type == peer_change_reset)
2228 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2229 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2230 else if (type == peer_change_reset_in)
2231 {
2232 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2233 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2234 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2235 else
2236 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2237 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2238 }
2239 else if (type == peer_change_reset_out)
2240 bgp_announce_route (peer, afi, safi);
2241}
2242
2243struct peer_flag_action
2244{
2245 /* Peer's flag. */
2246 u_int32_t flag;
2247
2248 /* This flag can be set for peer-group member. */
2249 u_char not_for_member;
2250
2251 /* Action when the flag is changed. */
2252 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002253
2254 /* Peer down cause */
2255 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002256};
2257
2258struct peer_flag_action peer_flag_action_list[] =
2259 {
2260 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2261 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2262 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2263 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2264 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002265 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002266 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002267 { 0, 0, 0 }
2268 };
2269
2270struct peer_flag_action peer_af_flag_action_list[] =
2271 {
2272 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2273 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2274 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2275 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2276 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2277 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2278 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2279 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2280 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2281 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2282 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2283 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2284 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002285 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002286 { 0, 0, 0 }
2287 };
2288
2289/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002290static int
paul718e3742002-12-13 20:15:29 +00002291peer_flag_action_set (struct peer_flag_action *action_list, int size,
2292 struct peer_flag_action *action, u_int32_t flag)
2293{
2294 int i;
2295 int found = 0;
2296 int reset_in = 0;
2297 int reset_out = 0;
2298 struct peer_flag_action *match = NULL;
2299
2300 /* Check peer's frag action. */
2301 for (i = 0; i < size; i++)
2302 {
2303 match = &action_list[i];
2304
2305 if (match->flag == 0)
2306 break;
2307
2308 if (match->flag & flag)
2309 {
2310 found = 1;
2311
2312 if (match->type == peer_change_reset_in)
2313 reset_in = 1;
2314 if (match->type == peer_change_reset_out)
2315 reset_out = 1;
2316 if (match->type == peer_change_reset)
2317 {
2318 reset_in = 1;
2319 reset_out = 1;
2320 }
2321 if (match->not_for_member)
2322 action->not_for_member = 1;
2323 }
2324 }
2325
2326 /* Set peer clear type. */
2327 if (reset_in && reset_out)
2328 action->type = peer_change_reset;
2329 else if (reset_in)
2330 action->type = peer_change_reset_in;
2331 else if (reset_out)
2332 action->type = peer_change_reset_out;
2333 else
2334 action->type = peer_change_none;
2335
2336 return found;
2337}
2338
paul94f2b392005-06-28 12:44:16 +00002339static void
paul718e3742002-12-13 20:15:29 +00002340peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2341{
2342 if (flag == PEER_FLAG_SHUTDOWN)
2343 {
2344 if (CHECK_FLAG (peer->flags, flag))
2345 {
hasso93406d82005-02-02 14:40:33 +00002346 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2347 peer_nsf_stop (peer);
2348
hasso0a486e52005-02-01 20:57:17 +00002349 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2350 if (peer->t_pmax_restart)
2351 {
2352 BGP_TIMER_OFF (peer->t_pmax_restart);
2353 if (BGP_DEBUG (events, EVENTS))
2354 zlog_debug ("%s Maximum-prefix restart timer canceled",
2355 peer->host);
2356 }
2357
hasso93406d82005-02-02 14:40:33 +00002358 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2359 peer_nsf_stop (peer);
2360
paul718e3742002-12-13 20:15:29 +00002361 if (peer->status == Established)
2362 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2363 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2364 else
2365 BGP_EVENT_ADD (peer, BGP_Stop);
2366 }
2367 else
2368 {
2369 peer->v_start = BGP_INIT_START_TIMER;
2370 BGP_EVENT_ADD (peer, BGP_Stop);
2371 }
2372 }
2373 else if (peer->status == Established)
2374 {
hassoc9502432005-02-01 22:01:48 +00002375 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2376 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2377 else if (flag == PEER_FLAG_PASSIVE)
2378 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002379 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002380 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002381
hassoc9502432005-02-01 22:01:48 +00002382 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2383 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002384 }
2385 else
2386 BGP_EVENT_ADD (peer, BGP_Stop);
2387}
2388
2389/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002390static int
paul718e3742002-12-13 20:15:29 +00002391peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2392{
2393 int found;
2394 int size;
2395 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002396 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002397 struct peer_flag_action action;
2398
2399 memset (&action, 0, sizeof (struct peer_flag_action));
2400 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2401
2402 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2403
2404 /* No flag action is found. */
2405 if (! found)
2406 return BGP_ERR_INVALID_FLAG;
2407
2408 /* Not for peer-group member. */
2409 if (action.not_for_member && peer_group_active (peer))
2410 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2411
2412 /* When unset the peer-group member's flag we have to check
2413 peer-group configuration. */
2414 if (! set && peer_group_active (peer))
2415 if (CHECK_FLAG (peer->group->conf->flags, flag))
2416 {
2417 if (flag == PEER_FLAG_SHUTDOWN)
2418 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2419 else
2420 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2421 }
2422
2423 /* Flag conflict check. */
2424 if (set
2425 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2426 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2427 return BGP_ERR_PEER_FLAG_CONFLICT;
2428
2429 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2430 {
2431 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2432 return 0;
2433 if (! set && ! CHECK_FLAG (peer->flags, flag))
2434 return 0;
2435 }
2436
2437 if (set)
2438 SET_FLAG (peer->flags, flag);
2439 else
2440 UNSET_FLAG (peer->flags, flag);
2441
2442 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2443 {
2444 if (action.type == peer_change_reset)
2445 peer_flag_modify_action (peer, flag);
2446
2447 return 0;
2448 }
2449
2450 /* peer-group member updates. */
2451 group = peer->group;
2452
paul1eb8ef22005-04-07 07:30:20 +00002453 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002454 {
2455 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2456 continue;
2457
2458 if (! set && ! CHECK_FLAG (peer->flags, flag))
2459 continue;
2460
2461 if (set)
2462 SET_FLAG (peer->flags, flag);
2463 else
2464 UNSET_FLAG (peer->flags, flag);
2465
2466 if (action.type == peer_change_reset)
2467 peer_flag_modify_action (peer, flag);
2468 }
2469 return 0;
2470}
2471
2472int
2473peer_flag_set (struct peer *peer, u_int32_t flag)
2474{
2475 return peer_flag_modify (peer, flag, 1);
2476}
2477
2478int
2479peer_flag_unset (struct peer *peer, u_int32_t flag)
2480{
2481 return peer_flag_modify (peer, flag, 0);
2482}
2483
paul94f2b392005-06-28 12:44:16 +00002484static int
paul718e3742002-12-13 20:15:29 +00002485peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2486{
2487 if (peer->af_group[afi][safi])
2488 return 1;
2489 return 0;
2490}
2491
paul94f2b392005-06-28 12:44:16 +00002492static int
paul718e3742002-12-13 20:15:29 +00002493peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2494 int set)
2495{
2496 int found;
2497 int size;
paul1eb8ef22005-04-07 07:30:20 +00002498 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002499 struct peer_group *group;
2500 struct peer_flag_action action;
2501
2502 memset (&action, 0, sizeof (struct peer_flag_action));
2503 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2504
2505 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2506
2507 /* No flag action is found. */
2508 if (! found)
2509 return BGP_ERR_INVALID_FLAG;
2510
2511 /* Adress family must be activated. */
2512 if (! peer->afc[afi][safi])
2513 return BGP_ERR_PEER_INACTIVE;
2514
2515 /* Not for peer-group member. */
2516 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2517 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2518
2519 /* Spcecial check for reflector client. */
2520 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2521 && peer_sort (peer) != BGP_PEER_IBGP)
2522 return BGP_ERR_NOT_INTERNAL_PEER;
2523
2524 /* Spcecial check for remove-private-AS. */
2525 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2526 && peer_sort (peer) == BGP_PEER_IBGP)
2527 return BGP_ERR_REMOVE_PRIVATE_AS;
2528
2529 /* When unset the peer-group member's flag we have to check
2530 peer-group configuration. */
2531 if (! set && peer->af_group[afi][safi])
2532 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2533 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2534
2535 /* When current flag configuration is same as requested one. */
2536 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2537 {
2538 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2539 return 0;
2540 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2541 return 0;
2542 }
2543
2544 if (set)
2545 SET_FLAG (peer->af_flags[afi][safi], flag);
2546 else
2547 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2548
2549 /* Execute action when peer is established. */
2550 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2551 && peer->status == Established)
2552 {
2553 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2554 bgp_clear_adj_in (peer, afi, safi);
2555 else
hassoe0701b72004-05-20 09:19:34 +00002556 {
2557 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2558 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2559 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2560 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2561 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2562 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2563 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2564 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2565
2566 peer_change_action (peer, afi, safi, action.type);
2567 }
2568
paul718e3742002-12-13 20:15:29 +00002569 }
2570
2571 /* Peer group member updates. */
2572 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2573 {
2574 group = peer->group;
2575
paul1eb8ef22005-04-07 07:30:20 +00002576 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002577 {
2578 if (! peer->af_group[afi][safi])
2579 continue;
2580
2581 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2582 continue;
2583
2584 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2585 continue;
2586
2587 if (set)
2588 SET_FLAG (peer->af_flags[afi][safi], flag);
2589 else
2590 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2591
2592 if (peer->status == Established)
2593 {
2594 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2595 bgp_clear_adj_in (peer, afi, safi);
2596 else
hassoe0701b72004-05-20 09:19:34 +00002597 {
2598 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2599 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2600 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2601 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2602 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2603 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2604 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2605 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2606
2607 peer_change_action (peer, afi, safi, action.type);
2608 }
paul718e3742002-12-13 20:15:29 +00002609 }
2610 }
2611 }
2612 return 0;
2613}
2614
2615int
2616peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2617{
2618 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2619}
2620
2621int
2622peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2623{
2624 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2625}
2626
2627/* EBGP multihop configuration. */
2628int
2629peer_ebgp_multihop_set (struct peer *peer, int ttl)
2630{
2631 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002632 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002633
2634 if (peer_sort (peer) == BGP_PEER_IBGP)
2635 return 0;
2636
2637 peer->ttl = ttl;
2638
2639 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2640 {
pauleb821182004-05-01 08:44:08 +00002641 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2642 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002643 }
2644 else
2645 {
2646 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002647 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002648 {
2649 if (peer_sort (peer) == BGP_PEER_IBGP)
2650 continue;
paul718e3742002-12-13 20:15:29 +00002651
pauleb821182004-05-01 08:44:08 +00002652 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002653
pauleb821182004-05-01 08:44:08 +00002654 if (peer->fd >= 0)
2655 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2656 }
paul718e3742002-12-13 20:15:29 +00002657 }
2658 return 0;
2659}
2660
2661int
2662peer_ebgp_multihop_unset (struct peer *peer)
2663{
2664 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002665 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002666
2667 if (peer_sort (peer) == BGP_PEER_IBGP)
2668 return 0;
2669
2670 if (peer_group_active (peer))
2671 peer->ttl = peer->group->conf->ttl;
2672 else
2673 peer->ttl = 1;
2674
2675 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2676 {
pauleb821182004-05-01 08:44:08 +00002677 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2678 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002679 }
2680 else
2681 {
2682 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002684 {
2685 if (peer_sort (peer) == BGP_PEER_IBGP)
2686 continue;
paul718e3742002-12-13 20:15:29 +00002687
pauleb821182004-05-01 08:44:08 +00002688 peer->ttl = 1;
2689
2690 if (peer->fd >= 0)
2691 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2692 }
paul718e3742002-12-13 20:15:29 +00002693 }
2694 return 0;
2695}
2696
2697/* Neighbor description. */
2698int
2699peer_description_set (struct peer *peer, char *desc)
2700{
2701 if (peer->desc)
2702 XFREE (MTYPE_PEER_DESC, peer->desc);
2703
2704 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2705
2706 return 0;
2707}
2708
2709int
2710peer_description_unset (struct peer *peer)
2711{
2712 if (peer->desc)
2713 XFREE (MTYPE_PEER_DESC, peer->desc);
2714
2715 peer->desc = NULL;
2716
2717 return 0;
2718}
2719
2720/* Neighbor update-source. */
2721int
paulfd79ac92004-10-13 05:06:08 +00002722peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002723{
2724 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002725 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002726
2727 if (peer->update_if)
2728 {
2729 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2730 && strcmp (peer->update_if, ifname) == 0)
2731 return 0;
2732
2733 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2734 peer->update_if = NULL;
2735 }
2736
2737 if (peer->update_source)
2738 {
2739 sockunion_free (peer->update_source);
2740 peer->update_source = NULL;
2741 }
2742
2743 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2744
2745 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2746 {
2747 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002748 {
2749 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2750 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2751 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2752 }
paul718e3742002-12-13 20:15:29 +00002753 else
2754 BGP_EVENT_ADD (peer, BGP_Stop);
2755 return 0;
2756 }
2757
2758 /* peer-group member updates. */
2759 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002760 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002761 {
2762 if (peer->update_if)
2763 {
2764 if (strcmp (peer->update_if, ifname) == 0)
2765 continue;
2766
2767 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2768 peer->update_if = NULL;
2769 }
2770
2771 if (peer->update_source)
2772 {
2773 sockunion_free (peer->update_source);
2774 peer->update_source = NULL;
2775 }
2776
2777 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2778
2779 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002780 {
2781 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2782 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2783 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2784 }
paul718e3742002-12-13 20:15:29 +00002785 else
2786 BGP_EVENT_ADD (peer, BGP_Stop);
2787 }
2788 return 0;
2789}
2790
2791int
2792peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2793{
2794 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002795 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002796
2797 if (peer->update_source)
2798 {
2799 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2800 && sockunion_cmp (peer->update_source, su) == 0)
2801 return 0;
2802 sockunion_free (peer->update_source);
2803 peer->update_source = NULL;
2804 }
2805
2806 if (peer->update_if)
2807 {
2808 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2809 peer->update_if = NULL;
2810 }
2811
2812 peer->update_source = sockunion_dup (su);
2813
2814 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2815 {
2816 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002817 {
2818 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2819 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2820 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2821 }
paul718e3742002-12-13 20:15:29 +00002822 else
2823 BGP_EVENT_ADD (peer, BGP_Stop);
2824 return 0;
2825 }
2826
2827 /* peer-group member updates. */
2828 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002829 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002830 {
2831 if (peer->update_source)
2832 {
2833 if (sockunion_cmp (peer->update_source, su) == 0)
2834 continue;
2835 sockunion_free (peer->update_source);
2836 peer->update_source = NULL;
2837 }
2838
2839 if (peer->update_if)
2840 {
2841 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2842 peer->update_if = NULL;
2843 }
2844
2845 peer->update_source = sockunion_dup (su);
2846
2847 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002848 {
2849 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2850 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2851 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2852 }
paul718e3742002-12-13 20:15:29 +00002853 else
2854 BGP_EVENT_ADD (peer, BGP_Stop);
2855 }
2856 return 0;
2857}
2858
2859int
2860peer_update_source_unset (struct peer *peer)
2861{
2862 union sockunion *su;
2863 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002864 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002865
2866 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2867 && ! peer->update_source
2868 && ! peer->update_if)
2869 return 0;
2870
2871 if (peer->update_source)
2872 {
2873 sockunion_free (peer->update_source);
2874 peer->update_source = NULL;
2875 }
2876 if (peer->update_if)
2877 {
2878 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2879 peer->update_if = NULL;
2880 }
2881
2882 if (peer_group_active (peer))
2883 {
2884 group = peer->group;
2885
2886 if (group->conf->update_source)
2887 {
2888 su = sockunion_dup (group->conf->update_source);
2889 peer->update_source = su;
2890 }
2891 else if (group->conf->update_if)
2892 peer->update_if =
2893 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2894 }
2895
2896 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2897 {
2898 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002899 {
2900 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2901 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2902 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2903 }
paul718e3742002-12-13 20:15:29 +00002904 else
2905 BGP_EVENT_ADD (peer, BGP_Stop);
2906 return 0;
2907 }
2908
2909 /* peer-group member updates. */
2910 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002911 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002912 {
2913 if (! peer->update_source && ! peer->update_if)
2914 continue;
2915
2916 if (peer->update_source)
2917 {
2918 sockunion_free (peer->update_source);
2919 peer->update_source = NULL;
2920 }
2921
2922 if (peer->update_if)
2923 {
2924 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2925 peer->update_if = NULL;
2926 }
2927
2928 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002929 {
2930 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2931 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2932 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2933 }
paul718e3742002-12-13 20:15:29 +00002934 else
2935 BGP_EVENT_ADD (peer, BGP_Stop);
2936 }
2937 return 0;
2938}
2939
2940int
2941peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002942 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002943{
2944 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002945 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002946
2947 /* Adress family must be activated. */
2948 if (! peer->afc[afi][safi])
2949 return BGP_ERR_PEER_INACTIVE;
2950
2951 /* Default originate can't be used for peer group memeber. */
2952 if (peer_is_group_member (peer, afi, safi))
2953 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2954
2955 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2956 || (rmap && ! peer->default_rmap[afi][safi].name)
2957 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2958 {
2959 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2960
2961 if (rmap)
2962 {
2963 if (peer->default_rmap[afi][safi].name)
2964 free (peer->default_rmap[afi][safi].name);
2965 peer->default_rmap[afi][safi].name = strdup (rmap);
2966 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2967 }
2968 }
2969
2970 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2971 {
2972 if (peer->status == Established && peer->afc_nego[afi][safi])
2973 bgp_default_originate (peer, afi, safi, 0);
2974 return 0;
2975 }
2976
2977 /* peer-group member updates. */
2978 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002979 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002980 {
2981 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2982
2983 if (rmap)
2984 {
2985 if (peer->default_rmap[afi][safi].name)
2986 free (peer->default_rmap[afi][safi].name);
2987 peer->default_rmap[afi][safi].name = strdup (rmap);
2988 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2989 }
2990
2991 if (peer->status == Established && peer->afc_nego[afi][safi])
2992 bgp_default_originate (peer, afi, safi, 0);
2993 }
2994 return 0;
2995}
2996
2997int
2998peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2999{
3000 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003001 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003002
3003 /* Adress family must be activated. */
3004 if (! peer->afc[afi][safi])
3005 return BGP_ERR_PEER_INACTIVE;
3006
3007 /* Default originate can't be used for peer group memeber. */
3008 if (peer_is_group_member (peer, afi, safi))
3009 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3010
3011 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3012 {
3013 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3014
3015 if (peer->default_rmap[afi][safi].name)
3016 free (peer->default_rmap[afi][safi].name);
3017 peer->default_rmap[afi][safi].name = NULL;
3018 peer->default_rmap[afi][safi].map = NULL;
3019 }
3020
3021 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3022 {
3023 if (peer->status == Established && peer->afc_nego[afi][safi])
3024 bgp_default_originate (peer, afi, safi, 1);
3025 return 0;
3026 }
3027
3028 /* peer-group member updates. */
3029 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003030 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003031 {
3032 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3033
3034 if (peer->default_rmap[afi][safi].name)
3035 free (peer->default_rmap[afi][safi].name);
3036 peer->default_rmap[afi][safi].name = NULL;
3037 peer->default_rmap[afi][safi].map = NULL;
3038
3039 if (peer->status == Established && peer->afc_nego[afi][safi])
3040 bgp_default_originate (peer, afi, safi, 1);
3041 }
3042 return 0;
3043}
3044
3045int
3046peer_port_set (struct peer *peer, u_int16_t port)
3047{
3048 peer->port = port;
3049 return 0;
3050}
3051
3052int
3053peer_port_unset (struct peer *peer)
3054{
3055 peer->port = BGP_PORT_DEFAULT;
3056 return 0;
3057}
3058
3059/* neighbor weight. */
3060int
3061peer_weight_set (struct peer *peer, u_int16_t weight)
3062{
3063 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003064 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003065
3066 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3067 peer->weight = weight;
3068
3069 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3070 return 0;
3071
3072 /* peer-group member updates. */
3073 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003074 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003075 {
3076 peer->weight = group->conf->weight;
3077 }
3078 return 0;
3079}
3080
3081int
3082peer_weight_unset (struct peer *peer)
3083{
3084 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003085 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003086
3087 /* Set default weight. */
3088 if (peer_group_active (peer))
3089 peer->weight = peer->group->conf->weight;
3090 else
3091 peer->weight = 0;
3092
3093 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3094
3095 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3096 return 0;
3097
3098 /* peer-group member updates. */
3099 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003100 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003101 {
3102 peer->weight = 0;
3103 }
3104 return 0;
3105}
3106
3107int
3108peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3109{
3110 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003111 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003112
3113 /* Not for peer group memeber. */
3114 if (peer_group_active (peer))
3115 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3116
3117 /* keepalive value check. */
3118 if (keepalive > 65535)
3119 return BGP_ERR_INVALID_VALUE;
3120
3121 /* Holdtime value check. */
3122 if (holdtime > 65535)
3123 return BGP_ERR_INVALID_VALUE;
3124
3125 /* Holdtime value must be either 0 or greater than 3. */
3126 if (holdtime < 3 && holdtime != 0)
3127 return BGP_ERR_INVALID_VALUE;
3128
3129 /* Set value to the configuration. */
3130 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3131 peer->holdtime = holdtime;
3132 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3133
3134 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3135 return 0;
3136
3137 /* peer-group member updates. */
3138 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003139 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003140 {
3141 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3142 peer->holdtime = group->conf->holdtime;
3143 peer->keepalive = group->conf->keepalive;
3144 }
3145 return 0;
3146}
3147
3148int
3149peer_timers_unset (struct peer *peer)
3150{
3151 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003152 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003153
3154 if (peer_group_active (peer))
3155 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3156
3157 /* Clear configuration. */
3158 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3159 peer->keepalive = 0;
3160 peer->holdtime = 0;
3161
3162 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3163 return 0;
3164
3165 /* peer-group member updates. */
3166 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003167 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003168 {
3169 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3170 peer->holdtime = 0;
3171 peer->keepalive = 0;
3172 }
3173
3174 return 0;
3175}
3176
3177int
3178peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3179{
3180 if (peer_group_active (peer))
3181 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3182
3183 if (connect > 65535)
3184 return BGP_ERR_INVALID_VALUE;
3185
3186 /* Set value to the configuration. */
3187 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3188 peer->connect = connect;
3189
3190 /* Set value to timer setting. */
3191 peer->v_connect = connect;
3192
3193 return 0;
3194}
3195
3196int
3197peer_timers_connect_unset (struct peer *peer)
3198{
3199 if (peer_group_active (peer))
3200 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3201
3202 /* Clear configuration. */
3203 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3204 peer->connect = 0;
3205
3206 /* Set timer setting to default value. */
3207 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3208
3209 return 0;
3210}
3211
3212int
3213peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3214{
3215 if (peer_group_active (peer))
3216 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3217
3218 if (routeadv > 600)
3219 return BGP_ERR_INVALID_VALUE;
3220
3221 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3222 peer->routeadv = routeadv;
3223 peer->v_routeadv = routeadv;
3224
3225 return 0;
3226}
3227
3228int
3229peer_advertise_interval_unset (struct peer *peer)
3230{
3231 if (peer_group_active (peer))
3232 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3233
3234 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3235 peer->routeadv = 0;
3236
3237 if (peer_sort (peer) == BGP_PEER_IBGP)
3238 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3239 else
3240 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3241
3242 return 0;
3243}
3244
paul718e3742002-12-13 20:15:29 +00003245/* neighbor interface */
3246int
paulfd79ac92004-10-13 05:06:08 +00003247peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003248{
3249 if (peer->ifname)
3250 free (peer->ifname);
3251 peer->ifname = strdup (str);
3252
3253 return 0;
3254}
3255
3256int
3257peer_interface_unset (struct peer *peer)
3258{
3259 if (peer->ifname)
3260 free (peer->ifname);
3261 peer->ifname = NULL;
3262
3263 return 0;
3264}
3265
3266/* Allow-as in. */
3267int
3268peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3269{
3270 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003271 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003272
3273 if (allow_num < 1 || allow_num > 10)
3274 return BGP_ERR_INVALID_VALUE;
3275
3276 if (peer->allowas_in[afi][safi] != allow_num)
3277 {
3278 peer->allowas_in[afi][safi] = allow_num;
3279 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3280 peer_change_action (peer, afi, safi, peer_change_reset_in);
3281 }
3282
3283 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3284 return 0;
3285
3286 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003287 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003288 {
3289 if (peer->allowas_in[afi][safi] != allow_num)
3290 {
3291 peer->allowas_in[afi][safi] = allow_num;
3292 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3293 peer_change_action (peer, afi, safi, peer_change_reset_in);
3294 }
3295
3296 }
3297 return 0;
3298}
3299
3300int
3301peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3302{
3303 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003304 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003305
3306 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3307 {
3308 peer->allowas_in[afi][safi] = 0;
3309 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3310 }
3311
3312 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3313 return 0;
3314
3315 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003316 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003317 {
3318 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3319 {
3320 peer->allowas_in[afi][safi] = 0;
3321 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3322 }
3323 }
3324 return 0;
3325}
3326
3327int
3328peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3329{
3330 struct bgp *bgp = peer->bgp;
3331 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003332 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003333
3334 if (peer_sort (peer) != BGP_PEER_EBGP
3335 && peer_sort (peer) != BGP_PEER_INTERNAL)
3336 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3337
3338 if (bgp->as == as)
3339 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3340
3341 if (peer_group_active (peer))
3342 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3343
3344 if (peer->change_local_as == as &&
3345 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3346 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3347 return 0;
3348
3349 peer->change_local_as = as;
3350 if (no_prepend)
3351 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3352 else
3353 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3354
3355 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3356 {
3357 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003358 {
3359 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3360 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3361 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3362 }
paul718e3742002-12-13 20:15:29 +00003363 else
3364 BGP_EVENT_ADD (peer, BGP_Stop);
3365
3366 return 0;
3367 }
3368
3369 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003370 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003371 {
3372 peer->change_local_as = as;
3373 if (no_prepend)
3374 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3375 else
3376 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3377
3378 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003379 {
3380 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3381 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3382 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3383 }
paul718e3742002-12-13 20:15:29 +00003384 else
3385 BGP_EVENT_ADD (peer, BGP_Stop);
3386 }
3387
3388 return 0;
3389}
3390
3391int
3392peer_local_as_unset (struct peer *peer)
3393{
3394 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003395 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003396
3397 if (peer_group_active (peer))
3398 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3399
3400 if (! peer->change_local_as)
3401 return 0;
3402
3403 peer->change_local_as = 0;
3404 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3405
3406 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3407 {
3408 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003409 {
3410 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3411 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3412 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3413 }
paul718e3742002-12-13 20:15:29 +00003414 else
3415 BGP_EVENT_ADD (peer, BGP_Stop);
3416
3417 return 0;
3418 }
3419
3420 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003421 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003422 {
3423 peer->change_local_as = 0;
3424 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3425
3426 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003427 {
3428 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3429 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3430 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3431 }
paul718e3742002-12-13 20:15:29 +00003432 else
3433 BGP_EVENT_ADD (peer, BGP_Stop);
3434 }
3435 return 0;
3436}
3437
Paul Jakma0df7c912008-07-21 21:02:49 +00003438/* Set password for authenticating with the peer. */
3439int
3440peer_password_set (struct peer *peer, const char *password)
3441{
3442 struct listnode *nn, *nnode;
3443 int len = password ? strlen(password) : 0;
3444 int ret = BGP_SUCCESS;
3445
3446 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3447 return BGP_ERR_INVALID_VALUE;
3448
3449 if (peer->password && strcmp (peer->password, password) == 0
3450 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3451 return 0;
3452
3453 if (peer->password)
3454 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3455
3456 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3457
3458 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3459 {
3460 if (peer->status == Established)
3461 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3462 else
3463 BGP_EVENT_ADD (peer, BGP_Stop);
3464
3465 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3466 }
3467
3468 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3469 {
3470 if (peer->password && strcmp (peer->password, password) == 0)
3471 continue;
3472
3473 if (peer->password)
3474 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3475
3476 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3477
3478 if (peer->status == Established)
3479 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3480 else
3481 BGP_EVENT_ADD (peer, BGP_Stop);
3482
3483 if (bgp_md5_set (peer) < 0)
3484 ret = BGP_ERR_TCPSIG_FAILED;
3485 }
3486
3487 return ret;
3488}
3489
3490int
3491peer_password_unset (struct peer *peer)
3492{
3493 struct listnode *nn, *nnode;
3494
3495 if (!peer->password
3496 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3497 return 0;
3498
3499 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3500 {
3501 if (peer_group_active (peer)
3502 && peer->group->conf->password
3503 && strcmp (peer->group->conf->password, peer->password) == 0)
3504 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3505
3506 if (peer->status == Established)
3507 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3508 else
3509 BGP_EVENT_ADD (peer, BGP_Stop);
3510
3511 if (peer->password)
3512 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3513
3514 peer->password = NULL;
3515
3516 bgp_md5_set (peer);
3517
3518 return 0;
3519 }
3520
3521 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3522 peer->password = NULL;
3523
3524 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3525 {
3526 if (!peer->password)
3527 continue;
3528
3529 if (peer->status == Established)
3530 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3531 else
3532 BGP_EVENT_ADD (peer, BGP_Stop);
3533
3534 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3535 peer->password = NULL;
3536
3537 bgp_md5_set (peer);
3538 }
3539
3540 return 0;
3541}
3542
paul718e3742002-12-13 20:15:29 +00003543/* Set distribute list to the peer. */
3544int
3545peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003546 const char *name)
paul718e3742002-12-13 20:15:29 +00003547{
3548 struct bgp_filter *filter;
3549 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003550 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003551
3552 if (! peer->afc[afi][safi])
3553 return BGP_ERR_PEER_INACTIVE;
3554
3555 if (direct != FILTER_IN && direct != FILTER_OUT)
3556 return BGP_ERR_INVALID_VALUE;
3557
3558 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3559 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3560
3561 filter = &peer->filter[afi][safi];
3562
3563 if (filter->plist[direct].name)
3564 return BGP_ERR_PEER_FILTER_CONFLICT;
3565
3566 if (filter->dlist[direct].name)
3567 free (filter->dlist[direct].name);
3568 filter->dlist[direct].name = strdup (name);
3569 filter->dlist[direct].alist = access_list_lookup (afi, name);
3570
3571 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3572 return 0;
3573
3574 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003575 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003576 {
3577 filter = &peer->filter[afi][safi];
3578
3579 if (! peer->af_group[afi][safi])
3580 continue;
3581
3582 if (filter->dlist[direct].name)
3583 free (filter->dlist[direct].name);
3584 filter->dlist[direct].name = strdup (name);
3585 filter->dlist[direct].alist = access_list_lookup (afi, name);
3586 }
3587
3588 return 0;
3589}
3590
3591int
3592peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3593{
3594 struct bgp_filter *filter;
3595 struct bgp_filter *gfilter;
3596 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003597 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003598
3599 if (! peer->afc[afi][safi])
3600 return BGP_ERR_PEER_INACTIVE;
3601
3602 if (direct != FILTER_IN && direct != FILTER_OUT)
3603 return BGP_ERR_INVALID_VALUE;
3604
3605 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3606 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3607
3608 filter = &peer->filter[afi][safi];
3609
3610 /* apply peer-group filter */
3611 if (peer->af_group[afi][safi])
3612 {
3613 gfilter = &peer->group->conf->filter[afi][safi];
3614
3615 if (gfilter->dlist[direct].name)
3616 {
3617 if (filter->dlist[direct].name)
3618 free (filter->dlist[direct].name);
3619 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3620 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3621 return 0;
3622 }
3623 }
3624
3625 if (filter->dlist[direct].name)
3626 free (filter->dlist[direct].name);
3627 filter->dlist[direct].name = NULL;
3628 filter->dlist[direct].alist = NULL;
3629
3630 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3631 return 0;
3632
3633 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003634 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003635 {
3636 filter = &peer->filter[afi][safi];
3637
3638 if (! peer->af_group[afi][safi])
3639 continue;
3640
3641 if (filter->dlist[direct].name)
3642 free (filter->dlist[direct].name);
3643 filter->dlist[direct].name = NULL;
3644 filter->dlist[direct].alist = NULL;
3645 }
3646
3647 return 0;
3648}
3649
3650/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003651static void
paul718e3742002-12-13 20:15:29 +00003652peer_distribute_update (struct access_list *access)
3653{
3654 afi_t afi;
3655 safi_t safi;
3656 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003657 struct listnode *mnode, *mnnode;
3658 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003659 struct bgp *bgp;
3660 struct peer *peer;
3661 struct peer_group *group;
3662 struct bgp_filter *filter;
3663
paul1eb8ef22005-04-07 07:30:20 +00003664 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003665 {
paul1eb8ef22005-04-07 07:30:20 +00003666 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003667 {
3668 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3669 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3670 {
3671 filter = &peer->filter[afi][safi];
3672
3673 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3674 {
3675 if (filter->dlist[direct].name)
3676 filter->dlist[direct].alist =
3677 access_list_lookup (afi, filter->dlist[direct].name);
3678 else
3679 filter->dlist[direct].alist = NULL;
3680 }
3681 }
3682 }
paul1eb8ef22005-04-07 07:30:20 +00003683 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003684 {
3685 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3686 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3687 {
3688 filter = &group->conf->filter[afi][safi];
3689
3690 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3691 {
3692 if (filter->dlist[direct].name)
3693 filter->dlist[direct].alist =
3694 access_list_lookup (afi, filter->dlist[direct].name);
3695 else
3696 filter->dlist[direct].alist = NULL;
3697 }
3698 }
3699 }
3700 }
3701}
3702
3703/* Set prefix list to the peer. */
3704int
3705peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003706 const char *name)
paul718e3742002-12-13 20:15:29 +00003707{
3708 struct bgp_filter *filter;
3709 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003710 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003711
3712 if (! peer->afc[afi][safi])
3713 return BGP_ERR_PEER_INACTIVE;
3714
3715 if (direct != FILTER_IN && direct != FILTER_OUT)
3716 return BGP_ERR_INVALID_VALUE;
3717
3718 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3719 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3720
3721 filter = &peer->filter[afi][safi];
3722
3723 if (filter->dlist[direct].name)
3724 return BGP_ERR_PEER_FILTER_CONFLICT;
3725
3726 if (filter->plist[direct].name)
3727 free (filter->plist[direct].name);
3728 filter->plist[direct].name = strdup (name);
3729 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3730
3731 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3732 return 0;
3733
3734 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003735 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003736 {
3737 filter = &peer->filter[afi][safi];
3738
3739 if (! peer->af_group[afi][safi])
3740 continue;
3741
3742 if (filter->plist[direct].name)
3743 free (filter->plist[direct].name);
3744 filter->plist[direct].name = strdup (name);
3745 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3746 }
3747 return 0;
3748}
3749
3750int
3751peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3752{
3753 struct bgp_filter *filter;
3754 struct bgp_filter *gfilter;
3755 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003756 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003757
3758 if (! peer->afc[afi][safi])
3759 return BGP_ERR_PEER_INACTIVE;
3760
3761 if (direct != FILTER_IN && direct != FILTER_OUT)
3762 return BGP_ERR_INVALID_VALUE;
3763
3764 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3765 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3766
3767 filter = &peer->filter[afi][safi];
3768
3769 /* apply peer-group filter */
3770 if (peer->af_group[afi][safi])
3771 {
3772 gfilter = &peer->group->conf->filter[afi][safi];
3773
3774 if (gfilter->plist[direct].name)
3775 {
3776 if (filter->plist[direct].name)
3777 free (filter->plist[direct].name);
3778 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3779 filter->plist[direct].plist = gfilter->plist[direct].plist;
3780 return 0;
3781 }
3782 }
3783
3784 if (filter->plist[direct].name)
3785 free (filter->plist[direct].name);
3786 filter->plist[direct].name = NULL;
3787 filter->plist[direct].plist = NULL;
3788
3789 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3790 return 0;
3791
3792 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003793 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003794 {
3795 filter = &peer->filter[afi][safi];
3796
3797 if (! peer->af_group[afi][safi])
3798 continue;
3799
3800 if (filter->plist[direct].name)
3801 free (filter->plist[direct].name);
3802 filter->plist[direct].name = NULL;
3803 filter->plist[direct].plist = NULL;
3804 }
3805
3806 return 0;
3807}
3808
3809/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003810static void
paul718e3742002-12-13 20:15:29 +00003811peer_prefix_list_update (struct prefix_list *plist)
3812{
paul1eb8ef22005-04-07 07:30:20 +00003813 struct listnode *mnode, *mnnode;
3814 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003815 struct bgp *bgp;
3816 struct peer *peer;
3817 struct peer_group *group;
3818 struct bgp_filter *filter;
3819 afi_t afi;
3820 safi_t safi;
3821 int direct;
3822
paul1eb8ef22005-04-07 07:30:20 +00003823 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003824 {
paul1eb8ef22005-04-07 07:30:20 +00003825 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003826 {
3827 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3828 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3829 {
3830 filter = &peer->filter[afi][safi];
3831
3832 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3833 {
3834 if (filter->plist[direct].name)
3835 filter->plist[direct].plist =
3836 prefix_list_lookup (afi, filter->plist[direct].name);
3837 else
3838 filter->plist[direct].plist = NULL;
3839 }
3840 }
3841 }
paul1eb8ef22005-04-07 07:30:20 +00003842 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003843 {
3844 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3845 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3846 {
3847 filter = &group->conf->filter[afi][safi];
3848
3849 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3850 {
3851 if (filter->plist[direct].name)
3852 filter->plist[direct].plist =
3853 prefix_list_lookup (afi, filter->plist[direct].name);
3854 else
3855 filter->plist[direct].plist = NULL;
3856 }
3857 }
3858 }
3859 }
3860}
3861
3862int
3863peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003864 const char *name)
paul718e3742002-12-13 20:15:29 +00003865{
3866 struct bgp_filter *filter;
3867 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003868 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003869
3870 if (! peer->afc[afi][safi])
3871 return BGP_ERR_PEER_INACTIVE;
3872
3873 if (direct != FILTER_IN && direct != FILTER_OUT)
3874 return BGP_ERR_INVALID_VALUE;
3875
3876 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3877 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3878
3879 filter = &peer->filter[afi][safi];
3880
3881 if (filter->aslist[direct].name)
3882 free (filter->aslist[direct].name);
3883 filter->aslist[direct].name = strdup (name);
3884 filter->aslist[direct].aslist = as_list_lookup (name);
3885
3886 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3887 return 0;
3888
3889 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003890 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003891 {
3892 filter = &peer->filter[afi][safi];
3893
3894 if (! peer->af_group[afi][safi])
3895 continue;
3896
3897 if (filter->aslist[direct].name)
3898 free (filter->aslist[direct].name);
3899 filter->aslist[direct].name = strdup (name);
3900 filter->aslist[direct].aslist = as_list_lookup (name);
3901 }
3902 return 0;
3903}
3904
3905int
3906peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3907{
3908 struct bgp_filter *filter;
3909 struct bgp_filter *gfilter;
3910 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003911 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003912
3913 if (! peer->afc[afi][safi])
3914 return BGP_ERR_PEER_INACTIVE;
3915
hassob5f29602005-05-25 21:00:28 +00003916 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003917 return BGP_ERR_INVALID_VALUE;
3918
hassob5f29602005-05-25 21:00:28 +00003919 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003920 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3921
3922 filter = &peer->filter[afi][safi];
3923
3924 /* apply peer-group filter */
3925 if (peer->af_group[afi][safi])
3926 {
3927 gfilter = &peer->group->conf->filter[afi][safi];
3928
3929 if (gfilter->aslist[direct].name)
3930 {
3931 if (filter->aslist[direct].name)
3932 free (filter->aslist[direct].name);
3933 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3934 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3935 return 0;
3936 }
3937 }
3938
3939 if (filter->aslist[direct].name)
3940 free (filter->aslist[direct].name);
3941 filter->aslist[direct].name = NULL;
3942 filter->aslist[direct].aslist = NULL;
3943
3944 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3945 return 0;
3946
3947 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003948 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003949 {
3950 filter = &peer->filter[afi][safi];
3951
3952 if (! peer->af_group[afi][safi])
3953 continue;
3954
3955 if (filter->aslist[direct].name)
3956 free (filter->aslist[direct].name);
3957 filter->aslist[direct].name = NULL;
3958 filter->aslist[direct].aslist = NULL;
3959 }
3960
3961 return 0;
3962}
3963
paul94f2b392005-06-28 12:44:16 +00003964static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003965peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003966{
3967 afi_t afi;
3968 safi_t safi;
3969 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003970 struct listnode *mnode, *mnnode;
3971 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003972 struct bgp *bgp;
3973 struct peer *peer;
3974 struct peer_group *group;
3975 struct bgp_filter *filter;
3976
paul1eb8ef22005-04-07 07:30:20 +00003977 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003978 {
paul1eb8ef22005-04-07 07:30:20 +00003979 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003980 {
3981 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3982 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3983 {
3984 filter = &peer->filter[afi][safi];
3985
3986 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3987 {
3988 if (filter->aslist[direct].name)
3989 filter->aslist[direct].aslist =
3990 as_list_lookup (filter->aslist[direct].name);
3991 else
3992 filter->aslist[direct].aslist = NULL;
3993 }
3994 }
3995 }
paul1eb8ef22005-04-07 07:30:20 +00003996 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003997 {
3998 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3999 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4000 {
4001 filter = &group->conf->filter[afi][safi];
4002
4003 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4004 {
4005 if (filter->aslist[direct].name)
4006 filter->aslist[direct].aslist =
4007 as_list_lookup (filter->aslist[direct].name);
4008 else
4009 filter->aslist[direct].aslist = NULL;
4010 }
4011 }
4012 }
4013 }
4014}
4015
4016/* Set route-map to the peer. */
4017int
4018peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004019 const char *name)
paul718e3742002-12-13 20:15:29 +00004020{
4021 struct bgp_filter *filter;
4022 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004023 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004024
4025 if (! peer->afc[afi][safi])
4026 return BGP_ERR_PEER_INACTIVE;
4027
paulfee0f4c2004-09-13 05:12:46 +00004028 if (direct != RMAP_IN && direct != RMAP_OUT &&
4029 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004030 return BGP_ERR_INVALID_VALUE;
4031
paulfee0f4c2004-09-13 05:12:46 +00004032 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4033 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004034 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4035
4036 filter = &peer->filter[afi][safi];
4037
4038 if (filter->map[direct].name)
4039 free (filter->map[direct].name);
4040
4041 filter->map[direct].name = strdup (name);
4042 filter->map[direct].map = route_map_lookup_by_name (name);
4043
4044 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4045 return 0;
4046
4047 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004048 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004049 {
4050 filter = &peer->filter[afi][safi];
4051
4052 if (! peer->af_group[afi][safi])
4053 continue;
4054
4055 if (filter->map[direct].name)
4056 free (filter->map[direct].name);
4057 filter->map[direct].name = strdup (name);
4058 filter->map[direct].map = route_map_lookup_by_name (name);
4059 }
4060 return 0;
4061}
4062
4063/* Unset route-map from the peer. */
4064int
4065peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4066{
4067 struct bgp_filter *filter;
4068 struct bgp_filter *gfilter;
4069 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004070 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004071
4072 if (! peer->afc[afi][safi])
4073 return BGP_ERR_PEER_INACTIVE;
4074
hassob5f29602005-05-25 21:00:28 +00004075 if (direct != RMAP_IN && direct != RMAP_OUT &&
4076 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004077 return BGP_ERR_INVALID_VALUE;
4078
hassob5f29602005-05-25 21:00:28 +00004079 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4080 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004081 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4082
4083 filter = &peer->filter[afi][safi];
4084
4085 /* apply peer-group filter */
4086 if (peer->af_group[afi][safi])
4087 {
4088 gfilter = &peer->group->conf->filter[afi][safi];
4089
4090 if (gfilter->map[direct].name)
4091 {
4092 if (filter->map[direct].name)
4093 free (filter->map[direct].name);
4094 filter->map[direct].name = strdup (gfilter->map[direct].name);
4095 filter->map[direct].map = gfilter->map[direct].map;
4096 return 0;
4097 }
4098 }
4099
4100 if (filter->map[direct].name)
4101 free (filter->map[direct].name);
4102 filter->map[direct].name = NULL;
4103 filter->map[direct].map = NULL;
4104
4105 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4106 return 0;
4107
4108 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004109 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004110 {
4111 filter = &peer->filter[afi][safi];
4112
4113 if (! peer->af_group[afi][safi])
4114 continue;
4115
4116 if (filter->map[direct].name)
4117 free (filter->map[direct].name);
4118 filter->map[direct].name = NULL;
4119 filter->map[direct].map = NULL;
4120 }
4121 return 0;
4122}
4123
4124/* Set unsuppress-map to the peer. */
4125int
paulfd79ac92004-10-13 05:06:08 +00004126peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4127 const char *name)
paul718e3742002-12-13 20:15:29 +00004128{
4129 struct bgp_filter *filter;
4130 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004131 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004132
4133 if (! peer->afc[afi][safi])
4134 return BGP_ERR_PEER_INACTIVE;
4135
4136 if (peer_is_group_member (peer, afi, safi))
4137 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4138
4139 filter = &peer->filter[afi][safi];
4140
4141 if (filter->usmap.name)
4142 free (filter->usmap.name);
4143
4144 filter->usmap.name = strdup (name);
4145 filter->usmap.map = route_map_lookup_by_name (name);
4146
4147 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4148 return 0;
4149
4150 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004151 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004152 {
4153 filter = &peer->filter[afi][safi];
4154
4155 if (! peer->af_group[afi][safi])
4156 continue;
4157
4158 if (filter->usmap.name)
4159 free (filter->usmap.name);
4160 filter->usmap.name = strdup (name);
4161 filter->usmap.map = route_map_lookup_by_name (name);
4162 }
4163 return 0;
4164}
4165
4166/* Unset route-map from the peer. */
4167int
4168peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4169{
4170 struct bgp_filter *filter;
4171 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004172 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004173
4174 if (! peer->afc[afi][safi])
4175 return BGP_ERR_PEER_INACTIVE;
4176
4177 if (peer_is_group_member (peer, afi, safi))
4178 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4179
4180 filter = &peer->filter[afi][safi];
4181
4182 if (filter->usmap.name)
4183 free (filter->usmap.name);
4184 filter->usmap.name = NULL;
4185 filter->usmap.map = NULL;
4186
4187 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4188 return 0;
4189
4190 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004191 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004192 {
4193 filter = &peer->filter[afi][safi];
4194
4195 if (! peer->af_group[afi][safi])
4196 continue;
4197
4198 if (filter->usmap.name)
4199 free (filter->usmap.name);
4200 filter->usmap.name = NULL;
4201 filter->usmap.map = NULL;
4202 }
4203 return 0;
4204}
4205
4206int
4207peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004208 u_int32_t max, u_char threshold,
4209 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004210{
4211 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004212 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004213
4214 if (! peer->afc[afi][safi])
4215 return BGP_ERR_PEER_INACTIVE;
4216
4217 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4218 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004219 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004220 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004221 if (warning)
4222 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4223 else
4224 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4225
4226 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4227 return 0;
4228
4229 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004230 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004231 {
4232 if (! peer->af_group[afi][safi])
4233 continue;
4234
4235 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4236 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004237 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004238 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004239 if (warning)
4240 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4241 else
4242 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4243 }
4244 return 0;
4245}
4246
4247int
4248peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4249{
4250 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004251 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004252
4253 if (! peer->afc[afi][safi])
4254 return BGP_ERR_PEER_INACTIVE;
4255
4256 /* apply peer-group config */
4257 if (peer->af_group[afi][safi])
4258 {
4259 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4260 PEER_FLAG_MAX_PREFIX))
4261 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4262 else
4263 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4264
4265 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4266 PEER_FLAG_MAX_PREFIX_WARNING))
4267 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4268 else
4269 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4270
4271 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004272 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004273 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004274 return 0;
4275 }
4276
4277 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4278 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4279 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004280 peer->pmax_threshold[afi][safi] = 0;
4281 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004282
4283 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4284 return 0;
4285
4286 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004287 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004288 {
4289 if (! peer->af_group[afi][safi])
4290 continue;
4291
4292 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4293 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4294 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004295 peer->pmax_threshold[afi][safi] = 0;
4296 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004297 }
4298 return 0;
4299}
4300
4301int
4302peer_clear (struct peer *peer)
4303{
4304 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4305 {
hasso0a486e52005-02-01 20:57:17 +00004306 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4307 {
4308 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4309 if (peer->t_pmax_restart)
4310 {
4311 BGP_TIMER_OFF (peer->t_pmax_restart);
4312 if (BGP_DEBUG (events, EVENTS))
4313 zlog_debug ("%s Maximum-prefix restart timer canceled",
4314 peer->host);
4315 }
4316 BGP_EVENT_ADD (peer, BGP_Start);
4317 return 0;
4318 }
4319
paul718e3742002-12-13 20:15:29 +00004320 peer->v_start = BGP_INIT_START_TIMER;
4321 if (peer->status == Established)
4322 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4323 BGP_NOTIFY_CEASE_ADMIN_RESET);
4324 else
4325 BGP_EVENT_ADD (peer, BGP_Stop);
4326 }
4327 return 0;
4328}
4329
4330int
4331peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4332 enum bgp_clear_type stype)
4333{
4334 if (peer->status != Established)
4335 return 0;
4336
4337 if (! peer->afc[afi][safi])
4338 return BGP_ERR_AF_UNCONFIGURED;
4339
paulfee0f4c2004-09-13 05:12:46 +00004340 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4341 {
4342 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4343 return 0;
4344 bgp_check_local_routes_rsclient (peer, afi, safi);
4345 bgp_soft_reconfig_rsclient (peer, afi, safi);
4346 }
4347
paul718e3742002-12-13 20:15:29 +00004348 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4349 bgp_announce_route (peer, afi, safi);
4350
4351 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4352 {
4353 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4354 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4355 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4356 {
4357 struct bgp_filter *filter = &peer->filter[afi][safi];
4358 u_char prefix_type;
4359
4360 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4361 prefix_type = ORF_TYPE_PREFIX;
4362 else
4363 prefix_type = ORF_TYPE_PREFIX_OLD;
4364
4365 if (filter->plist[FILTER_IN].plist)
4366 {
4367 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4368 bgp_route_refresh_send (peer, afi, safi,
4369 prefix_type, REFRESH_DEFER, 1);
4370 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4371 REFRESH_IMMEDIATE, 0);
4372 }
4373 else
4374 {
4375 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4376 bgp_route_refresh_send (peer, afi, safi,
4377 prefix_type, REFRESH_IMMEDIATE, 1);
4378 else
4379 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4380 }
4381 return 0;
4382 }
4383 }
4384
4385 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4386 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4387 {
4388 /* If neighbor has soft reconfiguration inbound flag.
4389 Use Adj-RIB-In database. */
4390 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4391 bgp_soft_reconfig_in (peer, afi, safi);
4392 else
4393 {
4394 /* If neighbor has route refresh capability, send route refresh
4395 message to the peer. */
4396 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4397 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4398 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4399 else
4400 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4401 }
4402 }
4403 return 0;
4404}
4405
paulfd79ac92004-10-13 05:06:08 +00004406/* Display peer uptime.*/
4407/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004408char *
4409peer_uptime (time_t uptime2, char *buf, size_t len)
4410{
4411 time_t uptime1;
4412 struct tm *tm;
4413
4414 /* Check buffer length. */
4415 if (len < BGP_UPTIME_LEN)
4416 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004417 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004418 /* XXX: should return status instead of buf... */
4419 snprintf (buf, len, "<error> ");
4420 return buf;
paul718e3742002-12-13 20:15:29 +00004421 }
4422
4423 /* If there is no connection has been done before print `never'. */
4424 if (uptime2 == 0)
4425 {
4426 snprintf (buf, len, "never ");
4427 return buf;
4428 }
4429
4430 /* Get current time. */
4431 uptime1 = time (NULL);
4432 uptime1 -= uptime2;
4433 tm = gmtime (&uptime1);
4434
4435 /* Making formatted timer strings. */
4436#define ONE_DAY_SECOND 60*60*24
4437#define ONE_WEEK_SECOND 60*60*24*7
4438
4439 if (uptime1 < ONE_DAY_SECOND)
4440 snprintf (buf, len, "%02d:%02d:%02d",
4441 tm->tm_hour, tm->tm_min, tm->tm_sec);
4442 else if (uptime1 < ONE_WEEK_SECOND)
4443 snprintf (buf, len, "%dd%02dh%02dm",
4444 tm->tm_yday, tm->tm_hour, tm->tm_min);
4445 else
4446 snprintf (buf, len, "%02dw%dd%02dh",
4447 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4448 return buf;
4449}
4450
paul94f2b392005-06-28 12:44:16 +00004451static void
paul718e3742002-12-13 20:15:29 +00004452bgp_config_write_filter (struct vty *vty, struct peer *peer,
4453 afi_t afi, safi_t safi)
4454{
4455 struct bgp_filter *filter;
4456 struct bgp_filter *gfilter = NULL;
4457 char *addr;
4458 int in = FILTER_IN;
4459 int out = FILTER_OUT;
4460
4461 addr = peer->host;
4462 filter = &peer->filter[afi][safi];
4463 if (peer->af_group[afi][safi])
4464 gfilter = &peer->group->conf->filter[afi][safi];
4465
4466 /* distribute-list. */
4467 if (filter->dlist[in].name)
4468 if (! gfilter || ! gfilter->dlist[in].name
4469 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4470 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4471 filter->dlist[in].name, VTY_NEWLINE);
4472 if (filter->dlist[out].name && ! gfilter)
4473 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4474 filter->dlist[out].name, VTY_NEWLINE);
4475
4476 /* prefix-list. */
4477 if (filter->plist[in].name)
4478 if (! gfilter || ! gfilter->plist[in].name
4479 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4480 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4481 filter->plist[in].name, VTY_NEWLINE);
4482 if (filter->plist[out].name && ! gfilter)
4483 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4484 filter->plist[out].name, VTY_NEWLINE);
4485
4486 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004487 if (filter->map[RMAP_IN].name)
4488 if (! gfilter || ! gfilter->map[RMAP_IN].name
4489 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004490 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004491 filter->map[RMAP_IN].name, VTY_NEWLINE);
4492 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004493 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004494 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4495 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4496 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4497 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4498 if (filter->map[RMAP_EXPORT].name)
4499 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4500 || strcmp (filter->map[RMAP_EXPORT].name,
4501 gfilter->map[RMAP_EXPORT].name) != 0)
4502 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4503 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004504
4505 /* unsuppress-map */
4506 if (filter->usmap.name && ! gfilter)
4507 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4508 filter->usmap.name, VTY_NEWLINE);
4509
4510 /* filter-list. */
4511 if (filter->aslist[in].name)
4512 if (! gfilter || ! gfilter->aslist[in].name
4513 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4514 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4515 filter->aslist[in].name, VTY_NEWLINE);
4516 if (filter->aslist[out].name && ! gfilter)
4517 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4518 filter->aslist[out].name, VTY_NEWLINE);
4519}
4520
4521/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004522static void
paul718e3742002-12-13 20:15:29 +00004523bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4524 struct peer *peer, afi_t afi, safi_t safi)
4525{
4526 struct bgp_filter *filter;
4527 struct peer *g_peer = NULL;
4528 char buf[SU_ADDRSTRLEN];
4529 char *addr;
4530
4531 filter = &peer->filter[afi][safi];
4532 addr = peer->host;
4533 if (peer_group_active (peer))
4534 g_peer = peer->group->conf;
4535
4536 /************************************
4537 ****** Global to the neighbor ******
4538 ************************************/
4539 if (afi == AFI_IP && safi == SAFI_UNICAST)
4540 {
4541 /* remote-as. */
4542 if (! peer_group_active (peer))
4543 {
4544 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4545 vty_out (vty, " neighbor %s peer-group%s", addr,
4546 VTY_NEWLINE);
4547 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004548 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004549 VTY_NEWLINE);
4550 }
4551 else
4552 {
4553 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004554 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004555 VTY_NEWLINE);
4556 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4557 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4558 peer->group->name, VTY_NEWLINE);
4559 }
4560
4561 /* local-as. */
4562 if (peer->change_local_as)
4563 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004564 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004565 peer->change_local_as,
4566 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4567 " no-prepend" : "", VTY_NEWLINE);
4568
4569 /* Description. */
4570 if (peer->desc)
4571 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4572 VTY_NEWLINE);
4573
4574 /* Shutdown. */
4575 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4576 if (! peer_group_active (peer) ||
4577 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4578 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4579
Paul Jakma0df7c912008-07-21 21:02:49 +00004580 /* Password. */
4581 if (peer->password)
4582 if (!peer_group_active (peer)
4583 || ! g_peer->password
4584 || strcmp (peer->password, g_peer->password) != 0)
4585 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4586 VTY_NEWLINE);
4587
paul718e3742002-12-13 20:15:29 +00004588 /* BGP port. */
4589 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004590 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004591 VTY_NEWLINE);
4592
4593 /* Local interface name. */
4594 if (peer->ifname)
4595 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4596 VTY_NEWLINE);
4597
4598 /* Passive. */
4599 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4600 if (! peer_group_active (peer) ||
4601 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4602 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4603
4604 /* EBGP multihop. */
4605 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4606 if (! peer_group_active (peer) ||
4607 g_peer->ttl != peer->ttl)
4608 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4609 VTY_NEWLINE);
4610
hasso6ffd2072005-02-02 14:50:11 +00004611 /* disable-connected-check. */
4612 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004613 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004614 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4615 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004616
4617 /* Update-source. */
4618 if (peer->update_if)
4619 if (! peer_group_active (peer) || ! g_peer->update_if
4620 || strcmp (g_peer->update_if, peer->update_if) != 0)
4621 vty_out (vty, " neighbor %s update-source %s%s", addr,
4622 peer->update_if, VTY_NEWLINE);
4623 if (peer->update_source)
4624 if (! peer_group_active (peer) || ! g_peer->update_source
4625 || sockunion_cmp (g_peer->update_source,
4626 peer->update_source) != 0)
4627 vty_out (vty, " neighbor %s update-source %s%s", addr,
4628 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4629 VTY_NEWLINE);
4630
paul718e3742002-12-13 20:15:29 +00004631 /* advertisement-interval */
4632 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4633 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4634 addr, peer->v_routeadv, VTY_NEWLINE);
4635
4636 /* timers. */
4637 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4638 && ! peer_group_active (peer))
4639 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4640 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4641
4642 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4643 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4644 peer->connect, VTY_NEWLINE);
4645
4646 /* Default weight. */
4647 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4648 if (! peer_group_active (peer) ||
4649 g_peer->weight != peer->weight)
4650 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4651 VTY_NEWLINE);
4652
paul718e3742002-12-13 20:15:29 +00004653 /* Dynamic capability. */
4654 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4655 if (! peer_group_active (peer) ||
4656 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4657 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4658 VTY_NEWLINE);
4659
4660 /* dont capability negotiation. */
4661 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4662 if (! peer_group_active (peer) ||
4663 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4664 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4665 VTY_NEWLINE);
4666
4667 /* override capability negotiation. */
4668 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4669 if (! peer_group_active (peer) ||
4670 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4671 vty_out (vty, " neighbor %s override-capability%s", addr,
4672 VTY_NEWLINE);
4673
4674 /* strict capability negotiation. */
4675 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4676 if (! peer_group_active (peer) ||
4677 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4678 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4679 VTY_NEWLINE);
4680
4681 if (! peer_group_active (peer))
4682 {
4683 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4684 {
4685 if (peer->afc[AFI_IP][SAFI_UNICAST])
4686 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4687 }
4688 else
4689 {
4690 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4691 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4692 }
4693 }
4694 }
4695
4696
4697 /************************************
4698 ****** Per AF to the neighbor ******
4699 ************************************/
4700
4701 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4702 {
4703 if (peer->af_group[afi][safi])
4704 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4705 peer->group->name, VTY_NEWLINE);
4706 else
4707 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4708 }
4709
4710 /* ORF capability. */
4711 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4712 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4713 if (! peer->af_group[afi][safi])
4714 {
4715 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4716
4717 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4718 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4719 vty_out (vty, " both");
4720 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4721 vty_out (vty, " send");
4722 else
4723 vty_out (vty, " receive");
4724 vty_out (vty, "%s", VTY_NEWLINE);
4725 }
4726
4727 /* Route reflector client. */
4728 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4729 && ! peer->af_group[afi][safi])
4730 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4731 VTY_NEWLINE);
4732
4733 /* Nexthop self. */
4734 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4735 && ! peer->af_group[afi][safi])
4736 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4737
4738 /* Remove private AS. */
4739 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4740 && ! peer->af_group[afi][safi])
4741 vty_out (vty, " neighbor %s remove-private-AS%s",
4742 addr, VTY_NEWLINE);
4743
4744 /* send-community print. */
4745 if (! peer->af_group[afi][safi])
4746 {
4747 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4748 {
4749 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4750 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4751 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4752 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4753 vty_out (vty, " neighbor %s send-community extended%s",
4754 addr, VTY_NEWLINE);
4755 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4756 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4757 }
4758 else
4759 {
4760 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4761 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4762 vty_out (vty, " no neighbor %s send-community both%s",
4763 addr, VTY_NEWLINE);
4764 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4765 vty_out (vty, " no neighbor %s send-community extended%s",
4766 addr, VTY_NEWLINE);
4767 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4768 vty_out (vty, " no neighbor %s send-community%s",
4769 addr, VTY_NEWLINE);
4770 }
4771 }
4772
4773 /* Default information */
4774 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4775 && ! peer->af_group[afi][safi])
4776 {
4777 vty_out (vty, " neighbor %s default-originate", addr);
4778 if (peer->default_rmap[afi][safi].name)
4779 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4780 vty_out (vty, "%s", VTY_NEWLINE);
4781 }
4782
4783 /* Soft reconfiguration inbound. */
4784 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4785 if (! peer->af_group[afi][safi] ||
4786 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4787 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4788 VTY_NEWLINE);
4789
4790 /* maximum-prefix. */
4791 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4792 if (! peer->af_group[afi][safi]
4793 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004794 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004795 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4796 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004797 {
hasso0a486e52005-02-01 20:57:17 +00004798 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4799 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4800 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4801 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4802 vty_out (vty, " warning-only");
4803 if (peer->pmax_restart[afi][safi])
4804 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4805 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004806 }
paul718e3742002-12-13 20:15:29 +00004807
4808 /* Route server client. */
4809 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4810 && ! peer->af_group[afi][safi])
4811 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4812
4813 /* Allow AS in. */
4814 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4815 if (! peer_group_active (peer)
4816 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4817 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4818 {
4819 if (peer->allowas_in[afi][safi] == 3)
4820 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4821 else
4822 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4823 peer->allowas_in[afi][safi], VTY_NEWLINE);
4824 }
4825
4826 /* Filter. */
4827 bgp_config_write_filter (vty, peer, afi, safi);
4828
4829 /* atribute-unchanged. */
4830 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4831 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4832 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4833 && ! peer->af_group[afi][safi])
4834 {
4835 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4836 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4837 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4838 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4839 else
4840 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4841 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4842 " as-path" : "",
4843 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4844 " next-hop" : "",
4845 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4846 " med" : "", VTY_NEWLINE);
4847 }
4848}
4849
4850/* Display "address-family" configuration header. */
4851void
4852bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4853 int *write)
4854{
4855 if (*write)
4856 return;
4857
4858 if (afi == AFI_IP && safi == SAFI_UNICAST)
4859 return;
4860
4861 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4862
4863 if (afi == AFI_IP)
4864 {
4865 if (safi == SAFI_MULTICAST)
4866 vty_out (vty, "ipv4 multicast");
4867 else if (safi == SAFI_MPLS_VPN)
4868 vty_out (vty, "vpnv4 unicast");
4869 }
4870 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004871 {
4872 vty_out (vty, "ipv6");
4873
4874 if (safi == SAFI_MULTICAST)
4875 vty_out (vty, " multicast");
4876 }
paul718e3742002-12-13 20:15:29 +00004877
4878 vty_out (vty, "%s", VTY_NEWLINE);
4879
4880 *write = 1;
4881}
4882
4883/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004884static int
paul718e3742002-12-13 20:15:29 +00004885bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4886 safi_t safi)
4887{
4888 int write = 0;
4889 struct peer *peer;
4890 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004891 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004892
4893 bgp_config_write_network (vty, bgp, afi, safi, &write);
4894
4895 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4896
paul1eb8ef22005-04-07 07:30:20 +00004897 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004898 {
4899 if (group->conf->afc[afi][safi])
4900 {
4901 bgp_config_write_family_header (vty, afi, safi, &write);
4902 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4903 }
4904 }
paul1eb8ef22005-04-07 07:30:20 +00004905 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004906 {
4907 if (peer->afc[afi][safi])
4908 {
4909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4910 {
4911 bgp_config_write_family_header (vty, afi, safi, &write);
4912 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4913 }
4914 }
4915 }
4916 if (write)
4917 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4918
4919 return write;
4920}
4921
4922int
4923bgp_config_write (struct vty *vty)
4924{
4925 int write = 0;
4926 struct bgp *bgp;
4927 struct peer_group *group;
4928 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004929 struct listnode *node, *nnode;
4930 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004931
4932 /* BGP Multiple instance. */
4933 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4934 {
4935 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4936 write++;
4937 }
4938
4939 /* BGP Config type. */
4940 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4941 {
4942 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4943 write++;
4944 }
4945
4946 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004947 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004948 {
4949 if (write)
4950 vty_out (vty, "!%s", VTY_NEWLINE);
4951
4952 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004953 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004954
4955 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4956 {
4957 if (bgp->name)
4958 vty_out (vty, " view %s", bgp->name);
4959 }
4960 vty_out (vty, "%s", VTY_NEWLINE);
4961
4962 /* No Synchronization */
4963 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4964 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4965
4966 /* BGP fast-external-failover. */
4967 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4968 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4969
4970 /* BGP router ID. */
4971 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4972 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4973 VTY_NEWLINE);
4974
paul848973c2003-08-13 00:32:49 +00004975 /* BGP log-neighbor-changes. */
4976 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4977 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4978
paul718e3742002-12-13 20:15:29 +00004979 /* BGP configuration. */
4980 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4981 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4982
4983 /* BGP default ipv4-unicast. */
4984 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4985 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4986
4987 /* BGP default local-preference. */
4988 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4989 vty_out (vty, " bgp default local-preference %d%s",
4990 bgp->default_local_pref, VTY_NEWLINE);
4991
4992 /* BGP client-to-client reflection. */
4993 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4994 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4995
4996 /* BGP cluster ID. */
4997 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4998 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4999 VTY_NEWLINE);
5000
hassoe0701b72004-05-20 09:19:34 +00005001 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005002 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005003 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5004 VTY_NEWLINE);
5005
5006 /* Confederation peer */
5007 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005008 {
hassoe0701b72004-05-20 09:19:34 +00005009 int i;
paul718e3742002-12-13 20:15:29 +00005010
hassoe0701b72004-05-20 09:19:34 +00005011 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005012
hassoe0701b72004-05-20 09:19:34 +00005013 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005014 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005015
hassoe0701b72004-05-20 09:19:34 +00005016 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005017 }
5018
5019 /* BGP enforce-first-as. */
5020 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5021 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5022
5023 /* BGP deterministic-med. */
5024 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5025 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005026
5027 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005028 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5029 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5030 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005031 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5032 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5033
paul718e3742002-12-13 20:15:29 +00005034 /* BGP bestpath method. */
5035 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5036 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005037 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5038 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005039 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5040 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5041 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5042 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5043 {
5044 vty_out (vty, " bgp bestpath med");
5045 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5046 vty_out (vty, " confed");
5047 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5048 vty_out (vty, " missing-as-worst");
5049 vty_out (vty, "%s", VTY_NEWLINE);
5050 }
5051
5052 /* BGP network import check. */
5053 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5054 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5055
5056 /* BGP scan interval. */
5057 bgp_config_write_scan_time (vty);
5058
5059 /* BGP flag dampening. */
5060 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5061 BGP_CONFIG_DAMPENING))
5062 bgp_config_write_damp (vty);
5063
5064 /* BGP static route configuration. */
5065 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5066
5067 /* BGP redistribute configuration. */
5068 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5069
5070 /* BGP timers configuration. */
5071 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5072 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5073 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5074 bgp->default_holdtime, VTY_NEWLINE);
5075
5076 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005077 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005078 {
5079 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5080 }
5081
5082 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005083 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005084 {
5085 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5086 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5087 }
5088
5089 /* Distance configuration. */
5090 bgp_config_write_distance (vty, bgp);
5091
5092 /* No auto-summary */
5093 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5094 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5095
5096 /* IPv4 multicast configuration. */
5097 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5098
5099 /* IPv4 VPN configuration. */
5100 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5101
5102 /* IPv6 unicast configuration. */
5103 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5104
Paul Jakma37a217a2007-04-10 19:20:29 +00005105 /* IPv6 multicast configuration. */
5106 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5107
paul718e3742002-12-13 20:15:29 +00005108 write++;
5109 }
5110 return write;
5111}
5112
5113void
paul94f2b392005-06-28 12:44:16 +00005114bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005115{
5116 memset (&bgp_master, 0, sizeof (struct bgp_master));
5117
5118 bm = &bgp_master;
5119 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005120 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005121 bm->port = BGP_PORT_DEFAULT;
5122 bm->master = thread_master_create ();
5123 bm->start_time = time (NULL);
5124}
paul200df112005-06-01 11:17:05 +00005125
paul718e3742002-12-13 20:15:29 +00005126
5127void
paul94f2b392005-06-28 12:44:16 +00005128bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005129{
paul718e3742002-12-13 20:15:29 +00005130 /* BGP VTY commands installation. */
5131 bgp_vty_init ();
5132
5133 /* Create BGP server socket. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +00005134 bgp_socket (NULL, bm->port, bm->address);
paul718e3742002-12-13 20:15:29 +00005135
5136 /* Init zebra. */
5137 bgp_zebra_init ();
5138
5139 /* BGP inits. */
5140 bgp_attr_init ();
5141 bgp_debug_init ();
5142 bgp_dump_init ();
5143 bgp_route_init ();
5144 bgp_route_map_init ();
5145 bgp_scan_init ();
5146 bgp_mplsvpn_init ();
5147
5148 /* Access list initialize. */
5149 access_list_init ();
5150 access_list_add_hook (peer_distribute_update);
5151 access_list_delete_hook (peer_distribute_update);
5152
5153 /* Filter list initialize. */
5154 bgp_filter_init ();
5155 as_list_add_hook (peer_aslist_update);
5156 as_list_delete_hook (peer_aslist_update);
5157
5158 /* Prefix list initialize.*/
5159 prefix_list_init ();
5160 prefix_list_add_hook (peer_prefix_list_update);
5161 prefix_list_delete_hook (peer_prefix_list_update);
5162
5163 /* Community list initialize. */
5164 bgp_clist = community_list_init ();
5165
5166#ifdef HAVE_SNMP
5167 bgp_snmp_init ();
5168#endif /* HAVE_SNMP */
5169}
paul545acaf2004-04-20 15:13:15 +00005170
5171void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005172bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005173{
paul545acaf2004-04-20 15:13:15 +00005174 struct bgp *bgp;
5175 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005176 struct listnode *node, *nnode;
5177 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005178
paul1eb8ef22005-04-07 07:30:20 +00005179 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5180 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005181 if (peer->status == Established)
5182 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5183 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005184
paul545acaf2004-04-20 15:13:15 +00005185 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005186
paule210cf92005-06-15 19:15:35 +00005187 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005188 {
5189 work_queue_free (bm->process_main_queue);
5190 bm->process_main_queue = NULL;
5191 }
paule210cf92005-06-15 19:15:35 +00005192 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005193 {
5194 work_queue_free (bm->process_rsclient_queue);
5195 bm->process_rsclient_queue = NULL;
5196 }
paul545acaf2004-04-20 15:13:15 +00005197}