blob: 0d462db93cc2fded34e6a7a8c15e3118fc1cf66d [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
Stephen Hemminger65957882010-01-15 16:22:10 +0300244/* time_t value that is monotonicly increasing
245 * and uneffected by adjustments to system clock
246 */
247time_t bgp_clock (void)
248{
249 struct timeval tv;
250
251 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
252 return tv.tv_sec;
253}
254
paul718e3742002-12-13 20:15:29 +0000255/* BGP timer configuration. */
256int
257bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
258{
259 bgp->default_keepalive = (keepalive < holdtime / 3
260 ? keepalive : holdtime / 3);
261 bgp->default_holdtime = holdtime;
262
263 return 0;
264}
265
266int
267bgp_timers_unset (struct bgp *bgp)
268{
269 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
270 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
271
272 return 0;
273}
274
275/* BGP confederation configuration. */
276int
277bgp_confederation_id_set (struct bgp *bgp, as_t as)
278{
279 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000280 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000281 int already_confed;
282
283 if (as == 0)
284 return BGP_ERR_INVALID_AS;
285
286 /* Remember - were we doing confederation before? */
287 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
288 bgp->confed_id = as;
289 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
290
291 /* If we were doing confederation already, this is just an external
292 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
293 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000294 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000295 {
296 /* We're looking for peers who's AS is not local or part of our
297 confederation. */
298 if (already_confed)
299 {
300 if (peer_sort (peer) == BGP_PEER_EBGP)
301 {
302 peer->local_as = as;
303 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000304 {
305 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
306 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
307 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
308 }
309
paul718e3742002-12-13 20:15:29 +0000310 else
311 BGP_EVENT_ADD (peer, BGP_Stop);
312 }
313 }
314 else
315 {
316 /* Not doign confederation before, so reset every non-local
317 session */
318 if (peer_sort (peer) != BGP_PEER_IBGP)
319 {
320 /* Reset the local_as to be our EBGP one */
321 if (peer_sort (peer) == BGP_PEER_EBGP)
322 peer->local_as = as;
323 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000324 {
325 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
326 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
327 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
328 }
paul718e3742002-12-13 20:15:29 +0000329 else
330 BGP_EVENT_ADD (peer, BGP_Stop);
331 }
332 }
333 }
334 return 0;
335}
336
337int
338bgp_confederation_id_unset (struct bgp *bgp)
339{
340 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000341 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000342
343 bgp->confed_id = 0;
344 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
345
paul1eb8ef22005-04-07 07:30:20 +0000346 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000347 {
348 /* We're looking for peers who's AS is not local */
349 if (peer_sort (peer) != BGP_PEER_IBGP)
350 {
351 peer->local_as = bgp->as;
352 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000353 {
354 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
355 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
356 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
357 }
358
paul718e3742002-12-13 20:15:29 +0000359 else
360 BGP_EVENT_ADD (peer, BGP_Stop);
361 }
362 }
363 return 0;
364}
365
366/* Is an AS part of the confed or not? */
367int
368bgp_confederation_peers_check (struct bgp *bgp, as_t as)
369{
370 int i;
371
372 if (! bgp)
373 return 0;
374
375 for (i = 0; i < bgp->confed_peers_cnt; i++)
376 if (bgp->confed_peers[i] == as)
377 return 1;
378
379 return 0;
380}
381
382/* Add an AS to the confederation set. */
383int
384bgp_confederation_peers_add (struct bgp *bgp, as_t as)
385{
386 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000387 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000388
389 if (! bgp)
390 return BGP_ERR_INVALID_BGP;
391
392 if (bgp->as == as)
393 return BGP_ERR_INVALID_AS;
394
395 if (bgp_confederation_peers_check (bgp, as))
396 return -1;
397
398 if (bgp->confed_peers)
399 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
400 bgp->confed_peers,
401 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
402 else
403 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
404 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
405
406 bgp->confed_peers[bgp->confed_peers_cnt] = as;
407 bgp->confed_peers_cnt++;
408
409 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
410 {
paul1eb8ef22005-04-07 07:30:20 +0000411 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000412 {
413 if (peer->as == as)
414 {
415 peer->local_as = bgp->as;
416 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000417 {
418 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
419 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
420 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
421 }
paul718e3742002-12-13 20:15:29 +0000422 else
423 BGP_EVENT_ADD (peer, BGP_Stop);
424 }
425 }
426 }
427 return 0;
428}
429
430/* Delete an AS from the confederation set. */
431int
432bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
433{
434 int i;
435 int j;
436 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000437 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000438
439 if (! bgp)
440 return -1;
441
442 if (! bgp_confederation_peers_check (bgp, as))
443 return -1;
444
445 for (i = 0; i < bgp->confed_peers_cnt; i++)
446 if (bgp->confed_peers[i] == as)
447 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
448 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
449
450 bgp->confed_peers_cnt--;
451
452 if (bgp->confed_peers_cnt == 0)
453 {
454 if (bgp->confed_peers)
455 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
456 bgp->confed_peers = NULL;
457 }
458 else
459 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
460 bgp->confed_peers,
461 bgp->confed_peers_cnt * sizeof (as_t));
462
463 /* Now reset any peer who's remote AS has just been removed from the
464 CONFED */
465 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
466 {
paul1eb8ef22005-04-07 07:30:20 +0000467 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000468 {
469 if (peer->as == as)
470 {
471 peer->local_as = bgp->confed_id;
472 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000473 {
474 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
475 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
476 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
477 }
paul718e3742002-12-13 20:15:29 +0000478 else
479 BGP_EVENT_ADD (peer, BGP_Stop);
480 }
481 }
482 }
483
484 return 0;
485}
486
487/* Local preference configuration. */
488int
489bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
490{
491 if (! bgp)
492 return -1;
493
paul718e3742002-12-13 20:15:29 +0000494 bgp->default_local_pref = local_pref;
495
496 return 0;
497}
498
499int
500bgp_default_local_preference_unset (struct bgp *bgp)
501{
502 if (! bgp)
503 return -1;
504
paul718e3742002-12-13 20:15:29 +0000505 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
506
507 return 0;
508}
509
paulfee0f4c2004-09-13 05:12:46 +0000510/* If peer is RSERVER_CLIENT in at least one address family and is not member
511 of a peer_group for that family, return 1.
512 Used to check wether the peer is included in list bgp->rsclient. */
513int
514peer_rsclient_active (struct peer *peer)
515{
516 int i;
517 int j;
518
519 for (i=AFI_IP; i < AFI_MAX; i++)
520 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
521 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
522 && ! peer->af_group[i][j])
523 return 1;
524 return 0;
525}
526
pauleb821182004-05-01 08:44:08 +0000527/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000528static int
529peer_cmp (struct peer *p1, struct peer *p2)
530{
pauleb821182004-05-01 08:44:08 +0000531 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000532}
533
534int
535peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
536{
537 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
538}
539
540/* Reset all address family specific configuration. */
541static void
542peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
543{
544 int i;
545 struct bgp_filter *filter;
546 char orf_name[BUFSIZ];
547
548 filter = &peer->filter[afi][safi];
549
550 /* Clear neighbor filter and route-map */
551 for (i = FILTER_IN; i < FILTER_MAX; i++)
552 {
553 if (filter->dlist[i].name)
554 {
555 free (filter->dlist[i].name);
556 filter->dlist[i].name = NULL;
557 }
558 if (filter->plist[i].name)
559 {
560 free (filter->plist[i].name);
561 filter->plist[i].name = NULL;
562 }
563 if (filter->aslist[i].name)
564 {
565 free (filter->aslist[i].name);
566 filter->aslist[i].name = NULL;
567 }
paulfee0f4c2004-09-13 05:12:46 +0000568 }
569 for (i = RMAP_IN; i < RMAP_MAX; i++)
570 {
paul718e3742002-12-13 20:15:29 +0000571 if (filter->map[i].name)
572 {
573 free (filter->map[i].name);
574 filter->map[i].name = NULL;
575 }
576 }
577
578 /* Clear unsuppress map. */
579 if (filter->usmap.name)
580 free (filter->usmap.name);
581 filter->usmap.name = NULL;
582 filter->usmap.map = NULL;
583
584 /* Clear neighbor's all address family flags. */
585 peer->af_flags[afi][safi] = 0;
586
587 /* Clear neighbor's all address family sflags. */
588 peer->af_sflags[afi][safi] = 0;
589
590 /* Clear neighbor's all address family capabilities. */
591 peer->af_cap[afi][safi] = 0;
592
593 /* Clear ORF info */
594 peer->orf_plist[afi][safi] = NULL;
595 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
596 prefix_bgp_orf_remove_all (orf_name);
597
598 /* Set default neighbor send-community. */
599 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
600 {
601 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
602 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
603 }
604
605 /* Clear neighbor default_originate_rmap */
606 if (peer->default_rmap[afi][safi].name)
607 free (peer->default_rmap[afi][safi].name);
608 peer->default_rmap[afi][safi].name = NULL;
609 peer->default_rmap[afi][safi].map = NULL;
610
611 /* Clear neighbor maximum-prefix */
612 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000613 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000614}
615
616/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000617static void
paul718e3742002-12-13 20:15:29 +0000618peer_global_config_reset (struct peer *peer)
619{
620 peer->weight = 0;
621 peer->change_local_as = 0;
622 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
623 if (peer->update_source)
624 {
625 sockunion_free (peer->update_source);
626 peer->update_source = NULL;
627 }
628 if (peer->update_if)
629 {
630 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
631 peer->update_if = NULL;
632 }
633
634 if (peer_sort (peer) == BGP_PEER_IBGP)
635 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
636 else
637 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
638
639 peer->flags = 0;
640 peer->config = 0;
641 peer->holdtime = 0;
642 peer->keepalive = 0;
643 peer->connect = 0;
644 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
645}
646
647/* Check peer's AS number and determin is this peer IBGP or EBGP */
648int
649peer_sort (struct peer *peer)
650{
651 struct bgp *bgp;
652
653 bgp = peer->bgp;
654
655 /* Peer-group */
656 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
657 {
658 if (peer->as)
659 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
660 else
661 {
662 struct peer *peer1;
663 peer1 = listnode_head (peer->group->peer);
664 if (peer1)
665 return (peer1->local_as == peer1->as
666 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
667 }
668 return BGP_PEER_INTERNAL;
669 }
670
671 /* Normal peer */
672 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
673 {
674 if (peer->local_as == 0)
675 return BGP_PEER_INTERNAL;
676
677 if (peer->local_as == peer->as)
678 {
679 if (peer->local_as == bgp->confed_id)
680 return BGP_PEER_EBGP;
681 else
682 return BGP_PEER_IBGP;
683 }
684
685 if (bgp_confederation_peers_check (bgp, peer->as))
686 return BGP_PEER_CONFED;
687
688 return BGP_PEER_EBGP;
689 }
690 else
691 {
692 return (peer->local_as == 0
693 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
694 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
695 }
696}
697
paul200df112005-06-01 11:17:05 +0000698static inline void
699peer_free (struct peer *peer)
700{
Paul Jakmaca058a32006-09-14 02:58:49 +0000701 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700702
703 bgp_unlock(peer->bgp);
704
Paul Jakmaca058a32006-09-14 02:58:49 +0000705 /* this /ought/ to have been done already through bgp_stop earlier,
706 * but just to be sure..
707 */
708 bgp_timer_set (peer);
709 BGP_READ_OFF (peer->t_read);
710 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000711 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000712
paul200df112005-06-01 11:17:05 +0000713 if (peer->desc)
714 XFREE (MTYPE_PEER_DESC, peer->desc);
715
716 /* Free allocated host character. */
717 if (peer->host)
718 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
719
720 /* Update source configuration. */
721 if (peer->update_source)
722 sockunion_free (peer->update_source);
723
724 if (peer->update_if)
725 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000726
727 if (peer->clear_node_queue)
728 work_queue_free (peer->clear_node_queue);
729
Paul Jakmaca058a32006-09-14 02:58:49 +0000730 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000731 memset (peer, 0, sizeof (struct peer));
732
733 XFREE (MTYPE_BGP_PEER, peer);
734}
735
736/* increase reference count on a struct peer */
737struct peer *
738peer_lock (struct peer *peer)
739{
740 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000741
paul200df112005-06-01 11:17:05 +0000742 peer->lock++;
743
744 return peer;
745}
746
747/* decrease reference count on a struct peer
748 * struct peer is freed and NULL returned if last reference
749 */
750struct peer *
751peer_unlock (struct peer *peer)
752{
753 assert (peer && (peer->lock > 0));
754
755 peer->lock--;
756
757 if (peer->lock == 0)
758 {
759#if 0
760 zlog_debug ("unlocked and freeing");
761 zlog_backtrace (LOG_DEBUG);
762#endif
763 peer_free (peer);
764 return NULL;
765 }
766
767#if 0
768 if (peer->lock == 1)
769 {
770 zlog_debug ("unlocked to 1");
771 zlog_backtrace (LOG_DEBUG);
772 }
773#endif
774
775 return peer;
776}
777
778/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000779static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000780peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000781{
782 afi_t afi;
783 safi_t safi;
784 struct peer *peer;
785 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000786
787 /* bgp argument is absolutely required */
788 assert (bgp);
789 if (!bgp)
790 return NULL;
791
paul718e3742002-12-13 20:15:29 +0000792 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000793 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000794
795 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000796 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000797 peer->v_start = BGP_INIT_START_TIMER;
798 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
799 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
800 peer->status = Idle;
801 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000802 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000803 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000804 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000805 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700806 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000807
808 /* Set default flags. */
809 for (afi = AFI_IP; afi < AFI_MAX; afi++)
810 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
811 {
812 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
813 {
814 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
815 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
816 }
817 peer->orf_plist[afi][safi] = NULL;
818 }
819 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
820
821 /* Create buffers. */
822 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
823 peer->obuf = stream_fifo_new ();
824 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
825
826 bgp_sync_init (peer);
827
828 /* Get service port number. */
829 sp = getservbyname ("bgp", "tcp");
830 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
831
832 return peer;
833}
834
835/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000836static struct peer *
paul718e3742002-12-13 20:15:29 +0000837peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
838 as_t remote_as, afi_t afi, safi_t safi)
839{
840 int active;
841 struct peer *peer;
842 char buf[SU_ADDRSTRLEN];
843
Paul Jakma6f585442006-10-22 19:13:07 +0000844 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000845 peer->su = *su;
846 peer->local_as = local_as;
847 peer->as = remote_as;
848 peer->local_id = bgp->router_id;
849 peer->v_holdtime = bgp->default_holdtime;
850 peer->v_keepalive = bgp->default_keepalive;
851 if (peer_sort (peer) == BGP_PEER_IBGP)
852 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
853 else
854 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000855
856 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000857 listnode_add_sort (bgp->peer, peer);
858
859 active = peer_active (peer);
860
861 if (afi && safi)
862 peer->afc[afi][safi] = 1;
863
Stephen Hemminger65957882010-01-15 16:22:10 +0300864 /* Last read and reset time set */
865 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000866
paul718e3742002-12-13 20:15:29 +0000867 /* Default TTL set. */
868 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
869
870 /* Make peer's address string. */
871 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000872 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000873
874 /* Set up peer's events and timers. */
875 if (! active && peer_active (peer))
876 bgp_timer_set (peer);
877
878 return peer;
879}
880
pauleb821182004-05-01 08:44:08 +0000881/* Make accept BGP peer. Called from bgp_accept (). */
882struct peer *
883peer_create_accept (struct bgp *bgp)
884{
885 struct peer *peer;
886
Paul Jakma6f585442006-10-22 19:13:07 +0000887 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000888
889 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000890 listnode_add_sort (bgp->peer, peer);
891
892 return peer;
893}
894
paul718e3742002-12-13 20:15:29 +0000895/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000896static void
paul718e3742002-12-13 20:15:29 +0000897peer_as_change (struct peer *peer, as_t as)
898{
899 int type;
900
901 /* Stop peer. */
902 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
903 {
904 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000905 {
906 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
907 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
908 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
909 }
paul718e3742002-12-13 20:15:29 +0000910 else
911 BGP_EVENT_ADD (peer, BGP_Stop);
912 }
913 type = peer_sort (peer);
914 peer->as = as;
915
paul848973c2003-08-13 00:32:49 +0000916 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
917 && ! bgp_confederation_peers_check (peer->bgp, as)
918 && peer->bgp->as != as)
919 peer->local_as = peer->bgp->confed_id;
920 else
921 peer->local_as = peer->bgp->as;
922
paul718e3742002-12-13 20:15:29 +0000923 /* Advertisement-interval reset */
924 if (peer_sort (peer) == BGP_PEER_IBGP)
925 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
926 else
927 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
928
929 /* TTL reset */
930 if (peer_sort (peer) == BGP_PEER_IBGP)
931 peer->ttl = 255;
932 else if (type == BGP_PEER_IBGP)
933 peer->ttl = 1;
934
935 /* reflector-client reset */
936 if (peer_sort (peer) != BGP_PEER_IBGP)
937 {
938 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
939 PEER_FLAG_REFLECTOR_CLIENT);
940 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
941 PEER_FLAG_REFLECTOR_CLIENT);
942 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
943 PEER_FLAG_REFLECTOR_CLIENT);
944 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
945 PEER_FLAG_REFLECTOR_CLIENT);
946 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
947 PEER_FLAG_REFLECTOR_CLIENT);
948 }
949
950 /* local-as reset */
951 if (peer_sort (peer) != BGP_PEER_EBGP)
952 {
953 peer->change_local_as = 0;
954 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
955 }
956}
957
958/* If peer does not exist, create new one. If peer already exists,
959 set AS number to the peer. */
960int
961peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
962 afi_t afi, safi_t safi)
963{
964 struct peer *peer;
965 as_t local_as;
966
967 peer = peer_lookup (bgp, su);
968
969 if (peer)
970 {
971 /* When this peer is a member of peer-group. */
972 if (peer->group)
973 {
974 if (peer->group->conf->as)
975 {
976 /* Return peer group's AS number. */
977 *as = peer->group->conf->as;
978 return BGP_ERR_PEER_GROUP_MEMBER;
979 }
980 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
981 {
982 if (bgp->as != *as)
983 {
984 *as = peer->as;
985 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
986 }
987 }
988 else
989 {
990 if (bgp->as == *as)
991 {
992 *as = peer->as;
993 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
994 }
995 }
996 }
997
998 /* Existing peer's AS number change. */
999 if (peer->as != *as)
1000 peer_as_change (peer, *as);
1001 }
1002 else
1003 {
1004
1005 /* If the peer is not part of our confederation, and its not an
1006 iBGP peer then spoof the source AS */
1007 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1008 && ! bgp_confederation_peers_check (bgp, *as)
1009 && bgp->as != *as)
1010 local_as = bgp->confed_id;
1011 else
1012 local_as = bgp->as;
1013
1014 /* If this is IPv4 unicast configuration and "no bgp default
1015 ipv4-unicast" is specified. */
1016
1017 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1018 && afi == AFI_IP && safi == SAFI_UNICAST)
1019 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1020 else
1021 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1022 }
1023
1024 return 0;
1025}
1026
1027/* Activate the peer or peer group for specified AFI and SAFI. */
1028int
1029peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1030{
1031 int active;
1032
1033 if (peer->afc[afi][safi])
1034 return 0;
1035
1036 /* Activate the address family configuration. */
1037 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1038 peer->afc[afi][safi] = 1;
1039 else
1040 {
1041 active = peer_active (peer);
1042
1043 peer->afc[afi][safi] = 1;
1044
1045 if (! active && peer_active (peer))
1046 bgp_timer_set (peer);
1047 else
1048 {
1049 if (peer->status == Established)
1050 {
1051 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1052 {
1053 peer->afc_adv[afi][safi] = 1;
1054 bgp_capability_send (peer, afi, safi,
1055 CAPABILITY_CODE_MP,
1056 CAPABILITY_ACTION_SET);
1057 if (peer->afc_recv[afi][safi])
1058 {
1059 peer->afc_nego[afi][safi] = 1;
1060 bgp_announce_route (peer, afi, safi);
1061 }
1062 }
1063 else
hassoe0701b72004-05-20 09:19:34 +00001064 {
1065 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1066 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1067 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1068 }
paul718e3742002-12-13 20:15:29 +00001069 }
1070 }
1071 }
1072 return 0;
1073}
1074
1075int
1076peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1077{
1078 struct peer_group *group;
1079 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001080 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001081
1082 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1083 {
1084 group = peer->group;
1085
paul1eb8ef22005-04-07 07:30:20 +00001086 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001087 {
1088 if (peer1->af_group[afi][safi])
1089 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1090 }
1091 }
1092 else
1093 {
1094 if (peer->af_group[afi][safi])
1095 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1096 }
1097
1098 if (! peer->afc[afi][safi])
1099 return 0;
1100
1101 /* De-activate the address family configuration. */
1102 peer->afc[afi][safi] = 0;
1103 peer_af_flag_reset (peer, afi, safi);
1104
1105 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1106 {
1107 if (peer->status == Established)
1108 {
1109 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1110 {
1111 peer->afc_adv[afi][safi] = 0;
1112 peer->afc_nego[afi][safi] = 0;
1113
1114 if (peer_active_nego (peer))
1115 {
1116 bgp_capability_send (peer, afi, safi,
1117 CAPABILITY_CODE_MP,
1118 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001119 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001120 peer->pcount[afi][safi] = 0;
1121 }
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 else
hassoe0701b72004-05-20 09:19:34 +00001130 {
1131 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1132 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1133 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1134 }
paul718e3742002-12-13 20:15:29 +00001135 }
1136 }
1137 return 0;
1138}
1139
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001140static void
hasso93406d82005-02-02 14:40:33 +00001141peer_nsf_stop (struct peer *peer)
1142{
1143 afi_t afi;
1144 safi_t safi;
1145
1146 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1147 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1148
1149 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienkofdc38db2011-07-17 19:33:21 +04001150 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001151 peer->nsf[afi][safi] = 0;
1152
1153 if (peer->t_gr_restart)
1154 {
1155 BGP_TIMER_OFF (peer->t_gr_restart);
1156 if (BGP_DEBUG (events, EVENTS))
1157 zlog_debug ("%s graceful restart timer stopped", peer->host);
1158 }
1159 if (peer->t_gr_stale)
1160 {
1161 BGP_TIMER_OFF (peer->t_gr_stale);
1162 if (BGP_DEBUG (events, EVENTS))
1163 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1164 }
1165 bgp_clear_route_all (peer);
1166}
1167
Paul Jakmaca058a32006-09-14 02:58:49 +00001168/* Delete peer from confguration.
1169 *
1170 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1171 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1172 *
1173 * This function /should/ take care to be idempotent, to guard against
1174 * it being called multiple times through stray events that come in
1175 * that happen to result in this function being called again. That
1176 * said, getting here for a "Deleted" peer is a bug in the neighbour
1177 * FSM.
1178 */
paul718e3742002-12-13 20:15:29 +00001179int
1180peer_delete (struct peer *peer)
1181{
1182 int i;
1183 afi_t afi;
1184 safi_t safi;
1185 struct bgp *bgp;
1186 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001187 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001188
Paul Jakmaca058a32006-09-14 02:58:49 +00001189 assert (peer->status != Deleted);
1190
paul718e3742002-12-13 20:15:29 +00001191 bgp = peer->bgp;
1192
hasso93406d82005-02-02 14:40:33 +00001193 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1194 peer_nsf_stop (peer);
1195
Chris Caputo228da422009-07-18 05:44:03 +00001196 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001197 relationship. */
1198 if (peer->group)
1199 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001200 if ((pn = listnode_lookup (peer->group->peer, peer)))
1201 {
1202 peer = peer_unlock (peer); /* group->peer list reference */
1203 list_delete_node (peer->group->peer, pn);
1204 }
paul718e3742002-12-13 20:15:29 +00001205 peer->group = NULL;
1206 }
paul200df112005-06-01 11:17:05 +00001207
paul718e3742002-12-13 20:15:29 +00001208 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001209 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1210 * executed after peer structure is deleted.
1211 */
hassoe0701b72004-05-20 09:19:34 +00001212 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001213 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001214 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001215
1216 /* Password configuration */
1217 if (peer->password)
1218 {
1219 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1220 peer->password = NULL;
1221
1222 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1223 bgp_md5_set (peer);
1224 }
1225
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001227
paul718e3742002-12-13 20:15:29 +00001228 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001229 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1230 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001231 {
Chris Caputo228da422009-07-18 05:44:03 +00001232 peer_unlock (peer); /* bgp peer list reference */
1233 list_delete_node (bgp->peer, pn);
1234 }
paul200df112005-06-01 11:17:05 +00001235
Chris Caputo228da422009-07-18 05:44:03 +00001236 if (peer_rsclient_active (peer)
1237 && (pn = listnode_lookup (bgp->rsclient, peer)))
1238 {
1239 peer_unlock (peer); /* rsclient list reference */
1240 list_delete_node (bgp->rsclient, pn);
1241
1242 /* Clear our own rsclient ribs. */
1243 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1244 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1245 if (CHECK_FLAG(peer->af_flags[afi][safi],
1246 PEER_FLAG_RSERVER_CLIENT))
1247 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001248 }
1249
1250 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1251 member of a peer_group. */
1252 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1253 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1254 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001255 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001256
paul200df112005-06-01 11:17:05 +00001257 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001258 if (peer->ibuf)
1259 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001260 if (peer->obuf)
1261 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001262 if (peer->work)
1263 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001264 peer->obuf = NULL;
1265 peer->work = peer->ibuf = NULL;
1266
paul718e3742002-12-13 20:15:29 +00001267 /* Local and remote addresses. */
1268 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001269 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001270 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001271 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001272 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001273
paul718e3742002-12-13 20:15:29 +00001274 /* Free filter related memory. */
1275 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1276 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1277 {
1278 filter = &peer->filter[afi][safi];
1279
1280 for (i = FILTER_IN; i < FILTER_MAX; i++)
1281 {
1282 if (filter->dlist[i].name)
1283 free (filter->dlist[i].name);
1284 if (filter->plist[i].name)
1285 free (filter->plist[i].name);
1286 if (filter->aslist[i].name)
1287 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001288
1289 filter->dlist[i].name = NULL;
1290 filter->plist[i].name = NULL;
1291 filter->aslist[i].name = NULL;
1292 }
1293 for (i = RMAP_IN; i < RMAP_MAX; i++)
1294 {
paul718e3742002-12-13 20:15:29 +00001295 if (filter->map[i].name)
1296 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001297 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001298 }
1299
1300 if (filter->usmap.name)
1301 free (filter->usmap.name);
1302
1303 if (peer->default_rmap[afi][safi].name)
1304 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001305
1306 filter->usmap.name = NULL;
1307 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001308 }
paul200df112005-06-01 11:17:05 +00001309
1310 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001311
1312 return 0;
1313}
1314
paul94f2b392005-06-28 12:44:16 +00001315static int
paul718e3742002-12-13 20:15:29 +00001316peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1317{
1318 return strcmp (g1->name, g2->name);
1319}
1320
1321/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001322static int
paul718e3742002-12-13 20:15:29 +00001323peer_group_active (struct peer *peer)
1324{
1325 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1326 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1327 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1328 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1329 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1330 return 1;
1331 return 0;
1332}
1333
1334/* Peer group cofiguration. */
1335static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001336peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001337{
1338 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1339 sizeof (struct peer_group));
1340}
1341
paul94f2b392005-06-28 12:44:16 +00001342static void
paul718e3742002-12-13 20:15:29 +00001343peer_group_free (struct peer_group *group)
1344{
1345 XFREE (MTYPE_PEER_GROUP, group);
1346}
1347
1348struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001349peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001350{
1351 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001352 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001353
paul1eb8ef22005-04-07 07:30:20 +00001354 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001355 {
1356 if (strcmp (group->name, name) == 0)
1357 return group;
1358 }
1359 return NULL;
1360}
1361
1362struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001363peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct peer_group *group;
1366
1367 group = peer_group_lookup (bgp, name);
1368 if (group)
1369 return group;
1370
1371 group = peer_group_new ();
1372 group->bgp = bgp;
1373 group->name = strdup (name);
1374 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001375 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001376 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1377 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001378 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001379 group->conf->group = group;
1380 group->conf->as = 0;
1381 group->conf->ttl = 1;
1382 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1383 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1384 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1385 group->conf->keepalive = 0;
1386 group->conf->holdtime = 0;
1387 group->conf->connect = 0;
1388 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1389 listnode_add_sort (bgp->group, group);
1390
1391 return 0;
1392}
1393
paul94f2b392005-06-28 12:44:16 +00001394static void
paul718e3742002-12-13 20:15:29 +00001395peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1396 afi_t afi, safi_t safi)
1397{
1398 int in = FILTER_IN;
1399 int out = FILTER_OUT;
1400 struct peer *conf;
1401 struct bgp_filter *pfilter;
1402 struct bgp_filter *gfilter;
1403
1404 conf = group->conf;
1405 pfilter = &peer->filter[afi][safi];
1406 gfilter = &conf->filter[afi][safi];
1407
1408 /* remote-as */
1409 if (conf->as)
1410 peer->as = conf->as;
1411
1412 /* remote-as */
1413 if (conf->change_local_as)
1414 peer->change_local_as = conf->change_local_as;
1415
1416 /* TTL */
1417 peer->ttl = conf->ttl;
1418
1419 /* Weight */
1420 peer->weight = conf->weight;
1421
1422 /* peer flags apply */
1423 peer->flags = conf->flags;
1424 /* peer af_flags apply */
1425 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1426 /* peer config apply */
1427 peer->config = conf->config;
1428
1429 /* peer timers apply */
1430 peer->holdtime = conf->holdtime;
1431 peer->keepalive = conf->keepalive;
1432 peer->connect = conf->connect;
1433 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1434 peer->v_connect = conf->connect;
1435 else
1436 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1437
1438 /* advertisement-interval reset */
1439 if (peer_sort (peer) == BGP_PEER_IBGP)
1440 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1441 else
1442 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1443
Paul Jakma0df7c912008-07-21 21:02:49 +00001444 /* password apply */
1445 if (peer->password)
1446 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1447
1448 if (conf->password)
1449 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1450 else
1451 peer->password = NULL;
1452
1453 bgp_md5_set (peer);
1454
paul718e3742002-12-13 20:15:29 +00001455 /* maximum-prefix */
1456 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001457 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001458 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001459
1460 /* allowas-in */
1461 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1462
paulfee0f4c2004-09-13 05:12:46 +00001463 /* route-server-client */
1464 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1465 {
1466 /* Make peer's RIB point to group's RIB. */
1467 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1468
1469 /* Import policy. */
1470 if (pfilter->map[RMAP_IMPORT].name)
1471 free (pfilter->map[RMAP_IMPORT].name);
1472 if (gfilter->map[RMAP_IMPORT].name)
1473 {
1474 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1475 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1476 }
1477 else
1478 {
1479 pfilter->map[RMAP_IMPORT].name = NULL;
1480 pfilter->map[RMAP_IMPORT].map = NULL;
1481 }
1482
1483 /* Export policy. */
1484 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1485 {
1486 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1487 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1488 }
1489 }
1490
paul718e3742002-12-13 20:15:29 +00001491 /* default-originate route-map */
1492 if (conf->default_rmap[afi][safi].name)
1493 {
1494 if (peer->default_rmap[afi][safi].name)
1495 free (peer->default_rmap[afi][safi].name);
1496 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1497 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1498 }
1499
1500 /* update-source apply */
1501 if (conf->update_source)
1502 {
1503 if (peer->update_source)
1504 sockunion_free (peer->update_source);
1505 if (peer->update_if)
1506 {
1507 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1508 peer->update_if = NULL;
1509 }
1510 peer->update_source = sockunion_dup (conf->update_source);
1511 }
1512 else if (conf->update_if)
1513 {
1514 if (peer->update_if)
1515 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1516 if (peer->update_source)
1517 {
1518 sockunion_free (peer->update_source);
1519 peer->update_source = NULL;
1520 }
1521 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1522 }
1523
1524 /* inbound filter apply */
1525 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1526 {
1527 if (pfilter->dlist[in].name)
1528 free (pfilter->dlist[in].name);
1529 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1530 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1531 }
1532 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1533 {
1534 if (pfilter->plist[in].name)
1535 free (pfilter->plist[in].name);
1536 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1537 pfilter->plist[in].plist = gfilter->plist[in].plist;
1538 }
1539 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1540 {
1541 if (pfilter->aslist[in].name)
1542 free (pfilter->aslist[in].name);
1543 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1544 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1545 }
paulfee0f4c2004-09-13 05:12:46 +00001546 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001547 {
paulfee0f4c2004-09-13 05:12:46 +00001548 if (pfilter->map[RMAP_IN].name)
1549 free (pfilter->map[RMAP_IN].name);
1550 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1551 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001552 }
1553
1554 /* outbound filter apply */
1555 if (gfilter->dlist[out].name)
1556 {
1557 if (pfilter->dlist[out].name)
1558 free (pfilter->dlist[out].name);
1559 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1560 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1561 }
1562 else
1563 {
1564 if (pfilter->dlist[out].name)
1565 free (pfilter->dlist[out].name);
1566 pfilter->dlist[out].name = NULL;
1567 pfilter->dlist[out].alist = NULL;
1568 }
1569 if (gfilter->plist[out].name)
1570 {
1571 if (pfilter->plist[out].name)
1572 free (pfilter->plist[out].name);
1573 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1574 pfilter->plist[out].plist = gfilter->plist[out].plist;
1575 }
1576 else
1577 {
1578 if (pfilter->plist[out].name)
1579 free (pfilter->plist[out].name);
1580 pfilter->plist[out].name = NULL;
1581 pfilter->plist[out].plist = NULL;
1582 }
1583 if (gfilter->aslist[out].name)
1584 {
1585 if (pfilter->aslist[out].name)
1586 free (pfilter->aslist[out].name);
1587 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1588 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1589 }
1590 else
1591 {
1592 if (pfilter->aslist[out].name)
1593 free (pfilter->aslist[out].name);
1594 pfilter->aslist[out].name = NULL;
1595 pfilter->aslist[out].aslist = NULL;
1596 }
paulfee0f4c2004-09-13 05:12:46 +00001597 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001598 {
paulfee0f4c2004-09-13 05:12:46 +00001599 if (pfilter->map[RMAP_OUT].name)
1600 free (pfilter->map[RMAP_OUT].name);
1601 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1602 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001603 }
1604 else
1605 {
paulfee0f4c2004-09-13 05:12:46 +00001606 if (pfilter->map[RMAP_OUT].name)
1607 free (pfilter->map[RMAP_OUT].name);
1608 pfilter->map[RMAP_OUT].name = NULL;
1609 pfilter->map[RMAP_OUT].map = NULL;
1610 }
1611
1612 /* RS-client's import/export route-maps. */
1613 if (gfilter->map[RMAP_IMPORT].name)
1614 {
1615 if (pfilter->map[RMAP_IMPORT].name)
1616 free (pfilter->map[RMAP_IMPORT].name);
1617 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1618 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1619 }
1620 else
1621 {
1622 if (pfilter->map[RMAP_IMPORT].name)
1623 free (pfilter->map[RMAP_IMPORT].name);
1624 pfilter->map[RMAP_IMPORT].name = NULL;
1625 pfilter->map[RMAP_IMPORT].map = NULL;
1626 }
1627 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1628 {
1629 if (pfilter->map[RMAP_EXPORT].name)
1630 free (pfilter->map[RMAP_EXPORT].name);
1631 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1632 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001633 }
1634
1635 if (gfilter->usmap.name)
1636 {
1637 if (pfilter->usmap.name)
1638 free (pfilter->usmap.name);
1639 pfilter->usmap.name = strdup (gfilter->usmap.name);
1640 pfilter->usmap.map = gfilter->usmap.map;
1641 }
1642 else
1643 {
1644 if (pfilter->usmap.name)
1645 free (pfilter->usmap.name);
1646 pfilter->usmap.name = NULL;
1647 pfilter->usmap.map = NULL;
1648 }
1649}
1650
1651/* Peer group's remote AS configuration. */
1652int
paulfd79ac92004-10-13 05:06:08 +00001653peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001654{
1655 struct peer_group *group;
1656 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001657 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001658
1659 group = peer_group_lookup (bgp, group_name);
1660 if (! group)
1661 return -1;
1662
1663 if (group->conf->as == *as)
1664 return 0;
1665
1666 /* When we setup peer-group AS number all peer group member's AS
1667 number must be updated to same number. */
1668 peer_as_change (group->conf, *as);
1669
paul1eb8ef22005-04-07 07:30:20 +00001670 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001671 {
1672 if (peer->as != *as)
1673 peer_as_change (peer, *as);
1674 }
1675
1676 return 0;
1677}
1678
1679int
1680peer_group_delete (struct peer_group *group)
1681{
1682 struct bgp *bgp;
1683 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001684 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001685
1686 bgp = group->bgp;
1687
paul1eb8ef22005-04-07 07:30:20 +00001688 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001689 {
1690 peer->group = NULL;
1691 peer_delete (peer);
1692 }
1693 list_delete (group->peer);
1694
1695 free (group->name);
1696 group->name = NULL;
1697
1698 group->conf->group = NULL;
1699 peer_delete (group->conf);
1700
1701 /* Delete from all peer_group list. */
1702 listnode_delete (bgp->group, group);
1703
1704 peer_group_free (group);
1705
1706 return 0;
1707}
1708
1709int
1710peer_group_remote_as_delete (struct peer_group *group)
1711{
1712 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001713 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001714
1715 if (! group->conf->as)
1716 return 0;
1717
paul1eb8ef22005-04-07 07:30:20 +00001718 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001719 {
1720 peer->group = NULL;
1721 peer_delete (peer);
1722 }
1723 list_delete_all_node (group->peer);
1724
1725 group->conf->as = 0;
1726
1727 return 0;
1728}
1729
1730/* Bind specified peer to peer group. */
1731int
1732peer_group_bind (struct bgp *bgp, union sockunion *su,
1733 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1734{
1735 struct peer *peer;
1736 int first_member = 0;
1737
1738 /* Check peer group's address family. */
1739 if (! group->conf->afc[afi][safi])
1740 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1741
1742 /* Lookup the peer. */
1743 peer = peer_lookup (bgp, su);
1744
1745 /* Create a new peer. */
1746 if (! peer)
1747 {
1748 if (! group->conf->as)
1749 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1750
1751 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1752 peer->group = group;
1753 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001754
Paul Jakmaca058a32006-09-14 02:58:49 +00001755 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001756 listnode_add (group->peer, peer);
1757 peer_group2peer_config_copy (group, peer, afi, safi);
1758
1759 return 0;
1760 }
1761
1762 /* When the peer already belongs to peer group, check the consistency. */
1763 if (peer->af_group[afi][safi])
1764 {
1765 if (strcmp (peer->group->name, group->name) != 0)
1766 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1767
1768 return 0;
1769 }
1770
1771 /* Check current peer group configuration. */
1772 if (peer_group_active (peer)
1773 && strcmp (peer->group->name, group->name) != 0)
1774 return BGP_ERR_PEER_GROUP_MISMATCH;
1775
1776 if (! group->conf->as)
1777 {
1778 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1779 && peer_sort (group->conf) != peer_sort (peer))
1780 {
1781 if (as)
1782 *as = peer->as;
1783 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1784 }
1785
1786 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1787 first_member = 1;
1788 }
1789
1790 peer->af_group[afi][safi] = 1;
1791 peer->afc[afi][safi] = 1;
1792 if (! peer->group)
1793 {
1794 peer->group = group;
paul200df112005-06-01 11:17:05 +00001795
Paul Jakmaca058a32006-09-14 02:58:49 +00001796 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001797 listnode_add (group->peer, peer);
1798 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001799 else
1800 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001801
1802 if (first_member)
1803 {
1804 /* Advertisement-interval reset */
1805 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1806 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1807 else
1808 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1809
1810 /* ebgp-multihop reset */
1811 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1812 group->conf->ttl = 255;
1813
1814 /* local-as reset */
1815 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1816 {
1817 group->conf->change_local_as = 0;
1818 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1819 }
1820 }
paulfee0f4c2004-09-13 05:12:46 +00001821
1822 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1823 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001824 struct listnode *pn;
1825
paulfee0f4c2004-09-13 05:12:46 +00001826 /* If it's not configured as RSERVER_CLIENT in any other address
1827 family, without being member of a peer_group, remove it from
1828 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001829 if (! peer_rsclient_active (peer)
1830 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001831 {
1832 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001833 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001834
1835 /* Clear our own rsclient rib for this afi/safi. */
1836 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001837 }
paulfee0f4c2004-09-13 05:12:46 +00001838
Paul Jakmab608d5b2008-07-02 02:12:07 +00001839 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001840
1841 /* Import policy. */
1842 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1843 {
1844 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1845 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1846 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1847 }
1848
1849 /* Export policy. */
1850 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1851 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1852 {
1853 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1854 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1855 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1856 }
1857 }
1858
paul718e3742002-12-13 20:15:29 +00001859 peer_group2peer_config_copy (group, peer, afi, safi);
1860
1861 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001862 {
1863 peer->last_reset = PEER_DOWN_RMAP_BIND;
1864 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1865 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1866 }
paul718e3742002-12-13 20:15:29 +00001867 else
1868 BGP_EVENT_ADD (peer, BGP_Stop);
1869
1870 return 0;
1871}
1872
1873int
1874peer_group_unbind (struct bgp *bgp, struct peer *peer,
1875 struct peer_group *group, afi_t afi, safi_t safi)
1876{
1877 if (! peer->af_group[afi][safi])
1878 return 0;
1879
1880 if (group != peer->group)
1881 return BGP_ERR_PEER_GROUP_MISMATCH;
1882
1883 peer->af_group[afi][safi] = 0;
1884 peer->afc[afi][safi] = 0;
1885 peer_af_flag_reset (peer, afi, safi);
1886
paulfee0f4c2004-09-13 05:12:46 +00001887 if (peer->rib[afi][safi])
1888 peer->rib[afi][safi] = NULL;
1889
paul718e3742002-12-13 20:15:29 +00001890 if (! peer_group_active (peer))
1891 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001892 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001893 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001894 listnode_delete (group->peer, peer);
1895 peer->group = NULL;
1896 if (group->conf->as)
1897 {
1898 peer_delete (peer);
1899 return 0;
1900 }
1901 peer_global_config_reset (peer);
1902 }
1903
1904 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001905 {
1906 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1907 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1908 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1909 }
paul718e3742002-12-13 20:15:29 +00001910 else
1911 BGP_EVENT_ADD (peer, BGP_Stop);
1912
1913 return 0;
1914}
1915
1916/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001917static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001918bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001919{
1920 struct bgp *bgp;
1921 afi_t afi;
1922 safi_t safi;
1923
paul200df112005-06-01 11:17:05 +00001924 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1925 return NULL;
1926
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001927 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001928 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001929 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001930
1931 bgp->peer = list_new ();
1932 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1933
1934 bgp->group = list_new ();
1935 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1936
paulfee0f4c2004-09-13 05:12:46 +00001937 bgp->rsclient = list_new ();
1938 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1939
paul718e3742002-12-13 20:15:29 +00001940 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1941 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1942 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001943 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1944 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1945 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001946 }
1947
1948 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1949 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1950 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001951 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1952 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001953
1954 bgp->as = *as;
1955
1956 if (name)
1957 bgp->name = strdup (name);
1958
1959 return bgp;
1960}
1961
1962/* Return first entry of BGP. */
1963struct bgp *
paul94f2b392005-06-28 12:44:16 +00001964bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001965{
1966 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001967 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001968 return NULL;
1969}
1970
1971/* Lookup BGP entry. */
1972struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001973bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001974{
1975 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001976 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001977
paul1eb8ef22005-04-07 07:30:20 +00001978 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001979 if (bgp->as == as
1980 && ((bgp->name == NULL && name == NULL)
1981 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1982 return bgp;
1983 return NULL;
1984}
1985
1986/* Lookup BGP structure by view name. */
1987struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001988bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001989{
1990 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001991 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001992
paul1eb8ef22005-04-07 07:30:20 +00001993 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001994 if ((bgp->name == NULL && name == NULL)
1995 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1996 return bgp;
1997 return NULL;
1998}
1999
2000/* Called from VTY commands. */
2001int
paulfd79ac92004-10-13 05:06:08 +00002002bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002003{
2004 struct bgp *bgp;
2005
2006 /* Multiple instance check. */
2007 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2008 {
2009 if (name)
2010 bgp = bgp_lookup_by_name (name);
2011 else
2012 bgp = bgp_get_default ();
2013
2014 /* Already exists. */
2015 if (bgp)
2016 {
2017 if (bgp->as != *as)
2018 {
2019 *as = bgp->as;
2020 return BGP_ERR_INSTANCE_MISMATCH;
2021 }
2022 *bgp_val = bgp;
2023 return 0;
2024 }
2025 }
2026 else
2027 {
2028 /* BGP instance name can not be specified for single instance. */
2029 if (name)
2030 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2031
2032 /* Get default BGP structure if exists. */
2033 bgp = bgp_get_default ();
2034
2035 if (bgp)
2036 {
2037 if (bgp->as != *as)
2038 {
2039 *as = bgp->as;
2040 return BGP_ERR_AS_MISMATCH;
2041 }
2042 *bgp_val = bgp;
2043 return 0;
2044 }
2045 }
2046
Sergey Y. Afoninf85bab12011-10-27 17:01:11 +04002047 bgp = bgp_create (as, name);
2048 bgp_router_id_set(bgp, &router_id_zebra);
2049 *bgp_val = bgp;
2050
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002051 /* Create BGP server socket, if first instance. */
2052 if (list_isempty(bm->bgp))
2053 {
2054 if (bgp_socket (bm->port, bm->address) < 0)
2055 return BGP_ERR_INVALID_VALUE;
2056 }
2057
paul718e3742002-12-13 20:15:29 +00002058 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002059
2060 return 0;
2061}
2062
2063/* Delete BGP instance. */
2064int
2065bgp_delete (struct bgp *bgp)
2066{
2067 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002068 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002069 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002070 struct listnode *next;
2071 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002072 int i;
2073
2074 /* Delete static route. */
2075 bgp_static_delete (bgp);
2076
2077 /* Unset redistribution. */
2078 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2079 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2080 if (i != ZEBRA_ROUTE_BGP)
2081 bgp_redistribute_unset (bgp, afi, i);
2082
paul1eb8ef22005-04-07 07:30:20 +00002083 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2084 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002085
Chris Caputo228da422009-07-18 05:44:03 +00002086 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2087 peer_group_delete (group);
2088
2089 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002090
2091 if (bgp->peer_self) {
2092 peer_delete(bgp->peer_self);
2093 bgp->peer_self = NULL;
2094 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002095
2096 /* Remove visibility via the master list - there may however still be
2097 * routes to be processed still referencing the struct bgp.
2098 */
2099 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002100 if (list_isempty(bm->bgp))
2101 bgp_close ();
2102
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002103 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002104
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002105 return 0;
2106}
2107
2108static void bgp_free (struct bgp *);
2109
2110void
2111bgp_lock (struct bgp *bgp)
2112{
2113 ++bgp->lock;
2114}
2115
2116void
2117bgp_unlock(struct bgp *bgp)
2118{
Chris Caputo228da422009-07-18 05:44:03 +00002119 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002120 if (--bgp->lock == 0)
2121 bgp_free (bgp);
2122}
2123
2124static void
2125bgp_free (struct bgp *bgp)
2126{
2127 afi_t afi;
2128 safi_t safi;
2129
2130 list_delete (bgp->group);
2131 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002132 list_delete (bgp->rsclient);
2133
paul718e3742002-12-13 20:15:29 +00002134 if (bgp->name)
2135 free (bgp->name);
2136
2137 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2138 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2139 {
2140 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002141 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002142 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002143 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002144 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002145 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002146 }
2147 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002148}
2149
2150struct peer *
2151peer_lookup (struct bgp *bgp, union sockunion *su)
2152{
2153 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002155
Steve Hillfc4dc592009-07-28 17:54:35 +01002156 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002157 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002158 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2159 if (sockunion_same (&peer->su, su)
2160 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2161 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002162 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002163 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002164 {
2165 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002166
Paul Jakma2158ad22009-07-28 18:10:55 +01002167 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2168 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2169 if (sockunion_same (&peer->su, su)
2170 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2171 return peer;
paul718e3742002-12-13 20:15:29 +00002172 }
2173 return NULL;
2174}
2175
2176struct peer *
2177peer_lookup_with_open (union sockunion *su, as_t remote_as,
2178 struct in_addr *remote_id, int *as)
2179{
2180 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002181 struct listnode *node;
2182 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002183 struct bgp *bgp;
2184
Steve Hillfc4dc592009-07-28 17:54:35 +01002185 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002186 return NULL;
2187
Paul Jakma9d878772009-08-05 16:25:16 +01002188 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002189 {
Paul Jakma9d878772009-08-05 16:25:16 +01002190 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2191 {
2192 if (sockunion_same (&peer->su, su)
2193 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2194 {
2195 if (peer->as == remote_as
2196 && peer->remote_id.s_addr == remote_id->s_addr)
2197 return peer;
2198 if (peer->as == remote_as)
2199 *as = 1;
2200 }
2201 }
2202
2203 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2204 {
2205 if (sockunion_same (&peer->su, su)
2206 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2207 {
2208 if (peer->as == remote_as
2209 && peer->remote_id.s_addr == 0)
2210 return peer;
2211 if (peer->as == remote_as)
2212 *as = 1;
2213 }
2214 }
paul718e3742002-12-13 20:15:29 +00002215 }
2216 return NULL;
2217}
2218
2219/* If peer is configured at least one address family return 1. */
2220int
2221peer_active (struct peer *peer)
2222{
2223 if (peer->afc[AFI_IP][SAFI_UNICAST]
2224 || peer->afc[AFI_IP][SAFI_MULTICAST]
2225 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2226 || peer->afc[AFI_IP6][SAFI_UNICAST]
2227 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2228 return 1;
2229 return 0;
2230}
2231
2232/* If peer is negotiated at least one address family return 1. */
2233int
2234peer_active_nego (struct peer *peer)
2235{
2236 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2237 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2238 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2239 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2240 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2241 return 1;
2242 return 0;
2243}
2244
2245/* peer_flag_change_type. */
2246enum peer_change_type
2247{
2248 peer_change_none,
2249 peer_change_reset,
2250 peer_change_reset_in,
2251 peer_change_reset_out,
2252};
2253
paul94f2b392005-06-28 12:44:16 +00002254static void
paul718e3742002-12-13 20:15:29 +00002255peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2256 enum peer_change_type type)
2257{
2258 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2259 return;
2260
2261 if (type == peer_change_reset)
2262 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2263 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2264 else if (type == peer_change_reset_in)
2265 {
2266 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2267 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2268 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2269 else
2270 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2271 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2272 }
2273 else if (type == peer_change_reset_out)
2274 bgp_announce_route (peer, afi, safi);
2275}
2276
2277struct peer_flag_action
2278{
2279 /* Peer's flag. */
2280 u_int32_t flag;
2281
2282 /* This flag can be set for peer-group member. */
2283 u_char not_for_member;
2284
2285 /* Action when the flag is changed. */
2286 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002287
2288 /* Peer down cause */
2289 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002290};
2291
Stephen Hemminger03621952009-07-21 16:27:20 -07002292static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002293 {
2294 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2295 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2296 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2297 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2298 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002299 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002300 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002301 { 0, 0, 0 }
2302 };
2303
Stephen Hemminger03621952009-07-21 16:27:20 -07002304static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002305 {
2306 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2307 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2308 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2309 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2310 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2311 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2312 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2313 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2314 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2315 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2316 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2317 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2318 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002319 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002320 { 0, 0, 0 }
2321 };
2322
2323/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002324static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002325peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002326 struct peer_flag_action *action, u_int32_t flag)
2327{
2328 int i;
2329 int found = 0;
2330 int reset_in = 0;
2331 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002332 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002333
2334 /* Check peer's frag action. */
2335 for (i = 0; i < size; i++)
2336 {
2337 match = &action_list[i];
2338
2339 if (match->flag == 0)
2340 break;
2341
2342 if (match->flag & flag)
2343 {
2344 found = 1;
2345
2346 if (match->type == peer_change_reset_in)
2347 reset_in = 1;
2348 if (match->type == peer_change_reset_out)
2349 reset_out = 1;
2350 if (match->type == peer_change_reset)
2351 {
2352 reset_in = 1;
2353 reset_out = 1;
2354 }
2355 if (match->not_for_member)
2356 action->not_for_member = 1;
2357 }
2358 }
2359
2360 /* Set peer clear type. */
2361 if (reset_in && reset_out)
2362 action->type = peer_change_reset;
2363 else if (reset_in)
2364 action->type = peer_change_reset_in;
2365 else if (reset_out)
2366 action->type = peer_change_reset_out;
2367 else
2368 action->type = peer_change_none;
2369
2370 return found;
2371}
2372
paul94f2b392005-06-28 12:44:16 +00002373static void
paul718e3742002-12-13 20:15:29 +00002374peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2375{
2376 if (flag == PEER_FLAG_SHUTDOWN)
2377 {
2378 if (CHECK_FLAG (peer->flags, flag))
2379 {
hasso93406d82005-02-02 14:40:33 +00002380 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2381 peer_nsf_stop (peer);
2382
hasso0a486e52005-02-01 20:57:17 +00002383 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2384 if (peer->t_pmax_restart)
2385 {
2386 BGP_TIMER_OFF (peer->t_pmax_restart);
2387 if (BGP_DEBUG (events, EVENTS))
2388 zlog_debug ("%s Maximum-prefix restart timer canceled",
2389 peer->host);
2390 }
2391
hasso93406d82005-02-02 14:40:33 +00002392 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2393 peer_nsf_stop (peer);
2394
paul718e3742002-12-13 20:15:29 +00002395 if (peer->status == Established)
2396 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2397 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2398 else
2399 BGP_EVENT_ADD (peer, BGP_Stop);
2400 }
2401 else
2402 {
2403 peer->v_start = BGP_INIT_START_TIMER;
2404 BGP_EVENT_ADD (peer, BGP_Stop);
2405 }
2406 }
2407 else if (peer->status == Established)
2408 {
hassoc9502432005-02-01 22:01:48 +00002409 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2410 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2411 else if (flag == PEER_FLAG_PASSIVE)
2412 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002413 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002414 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002415
hassoc9502432005-02-01 22:01:48 +00002416 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2417 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002418 }
2419 else
2420 BGP_EVENT_ADD (peer, BGP_Stop);
2421}
2422
2423/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002424static int
paul718e3742002-12-13 20:15:29 +00002425peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2426{
2427 int found;
2428 int size;
2429 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002430 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002431 struct peer_flag_action action;
2432
2433 memset (&action, 0, sizeof (struct peer_flag_action));
2434 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2435
2436 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2437
2438 /* No flag action is found. */
2439 if (! found)
2440 return BGP_ERR_INVALID_FLAG;
2441
2442 /* Not for peer-group member. */
2443 if (action.not_for_member && peer_group_active (peer))
2444 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2445
2446 /* When unset the peer-group member's flag we have to check
2447 peer-group configuration. */
2448 if (! set && peer_group_active (peer))
2449 if (CHECK_FLAG (peer->group->conf->flags, flag))
2450 {
2451 if (flag == PEER_FLAG_SHUTDOWN)
2452 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2453 else
2454 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2455 }
2456
2457 /* Flag conflict check. */
2458 if (set
2459 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2460 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2461 return BGP_ERR_PEER_FLAG_CONFLICT;
2462
2463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2464 {
2465 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2466 return 0;
2467 if (! set && ! CHECK_FLAG (peer->flags, flag))
2468 return 0;
2469 }
2470
2471 if (set)
2472 SET_FLAG (peer->flags, flag);
2473 else
2474 UNSET_FLAG (peer->flags, flag);
2475
2476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2477 {
2478 if (action.type == peer_change_reset)
2479 peer_flag_modify_action (peer, flag);
2480
2481 return 0;
2482 }
2483
2484 /* peer-group member updates. */
2485 group = peer->group;
2486
paul1eb8ef22005-04-07 07:30:20 +00002487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002488 {
2489 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2490 continue;
2491
2492 if (! set && ! CHECK_FLAG (peer->flags, flag))
2493 continue;
2494
2495 if (set)
2496 SET_FLAG (peer->flags, flag);
2497 else
2498 UNSET_FLAG (peer->flags, flag);
2499
2500 if (action.type == peer_change_reset)
2501 peer_flag_modify_action (peer, flag);
2502 }
2503 return 0;
2504}
2505
2506int
2507peer_flag_set (struct peer *peer, u_int32_t flag)
2508{
2509 return peer_flag_modify (peer, flag, 1);
2510}
2511
2512int
2513peer_flag_unset (struct peer *peer, u_int32_t flag)
2514{
2515 return peer_flag_modify (peer, flag, 0);
2516}
2517
paul94f2b392005-06-28 12:44:16 +00002518static int
paul718e3742002-12-13 20:15:29 +00002519peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2520{
2521 if (peer->af_group[afi][safi])
2522 return 1;
2523 return 0;
2524}
2525
paul94f2b392005-06-28 12:44:16 +00002526static int
paul718e3742002-12-13 20:15:29 +00002527peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2528 int set)
2529{
2530 int found;
2531 int size;
paul1eb8ef22005-04-07 07:30:20 +00002532 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002533 struct peer_group *group;
2534 struct peer_flag_action action;
2535
2536 memset (&action, 0, sizeof (struct peer_flag_action));
2537 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2538
2539 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2540
2541 /* No flag action is found. */
2542 if (! found)
2543 return BGP_ERR_INVALID_FLAG;
2544
2545 /* Adress family must be activated. */
2546 if (! peer->afc[afi][safi])
2547 return BGP_ERR_PEER_INACTIVE;
2548
2549 /* Not for peer-group member. */
2550 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2551 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2552
2553 /* Spcecial check for reflector client. */
2554 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2555 && peer_sort (peer) != BGP_PEER_IBGP)
2556 return BGP_ERR_NOT_INTERNAL_PEER;
2557
2558 /* Spcecial check for remove-private-AS. */
2559 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2560 && peer_sort (peer) == BGP_PEER_IBGP)
2561 return BGP_ERR_REMOVE_PRIVATE_AS;
2562
2563 /* When unset the peer-group member's flag we have to check
2564 peer-group configuration. */
2565 if (! set && peer->af_group[afi][safi])
2566 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2567 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2568
2569 /* When current flag configuration is same as requested one. */
2570 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2571 {
2572 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2573 return 0;
2574 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2575 return 0;
2576 }
2577
2578 if (set)
2579 SET_FLAG (peer->af_flags[afi][safi], flag);
2580 else
2581 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2582
2583 /* Execute action when peer is established. */
2584 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2585 && peer->status == Established)
2586 {
2587 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2588 bgp_clear_adj_in (peer, afi, safi);
2589 else
hassoe0701b72004-05-20 09:19:34 +00002590 {
2591 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2592 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2593 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2594 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2595 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2596 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2597 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2598 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2599
2600 peer_change_action (peer, afi, safi, action.type);
2601 }
2602
paul718e3742002-12-13 20:15:29 +00002603 }
2604
2605 /* Peer group member updates. */
2606 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2607 {
2608 group = peer->group;
2609
paul1eb8ef22005-04-07 07:30:20 +00002610 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002611 {
2612 if (! peer->af_group[afi][safi])
2613 continue;
2614
2615 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2616 continue;
2617
2618 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2619 continue;
2620
2621 if (set)
2622 SET_FLAG (peer->af_flags[afi][safi], flag);
2623 else
2624 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2625
2626 if (peer->status == Established)
2627 {
2628 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2629 bgp_clear_adj_in (peer, afi, safi);
2630 else
hassoe0701b72004-05-20 09:19:34 +00002631 {
2632 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2633 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2634 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2635 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2636 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2637 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2638 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2639 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2640
2641 peer_change_action (peer, afi, safi, action.type);
2642 }
paul718e3742002-12-13 20:15:29 +00002643 }
2644 }
2645 }
2646 return 0;
2647}
2648
2649int
2650peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2651{
2652 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2653}
2654
2655int
2656peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2657{
2658 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2659}
2660
2661/* EBGP multihop configuration. */
2662int
2663peer_ebgp_multihop_set (struct peer *peer, int ttl)
2664{
2665 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002666 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002667
2668 if (peer_sort (peer) == BGP_PEER_IBGP)
2669 return 0;
2670
2671 peer->ttl = ttl;
2672
2673 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2674 {
pauleb821182004-05-01 08:44:08 +00002675 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2676 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002677 }
2678 else
2679 {
2680 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002681 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002682 {
2683 if (peer_sort (peer) == BGP_PEER_IBGP)
2684 continue;
paul718e3742002-12-13 20:15:29 +00002685
pauleb821182004-05-01 08:44:08 +00002686 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002687
pauleb821182004-05-01 08:44:08 +00002688 if (peer->fd >= 0)
2689 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2690 }
paul718e3742002-12-13 20:15:29 +00002691 }
2692 return 0;
2693}
2694
2695int
2696peer_ebgp_multihop_unset (struct peer *peer)
2697{
2698 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002699 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002700
2701 if (peer_sort (peer) == BGP_PEER_IBGP)
2702 return 0;
2703
2704 if (peer_group_active (peer))
2705 peer->ttl = peer->group->conf->ttl;
2706 else
2707 peer->ttl = 1;
2708
2709 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2710 {
pauleb821182004-05-01 08:44:08 +00002711 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2712 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002713 }
2714 else
2715 {
2716 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002717 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002718 {
2719 if (peer_sort (peer) == BGP_PEER_IBGP)
2720 continue;
paul718e3742002-12-13 20:15:29 +00002721
pauleb821182004-05-01 08:44:08 +00002722 peer->ttl = 1;
2723
2724 if (peer->fd >= 0)
2725 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2726 }
paul718e3742002-12-13 20:15:29 +00002727 }
2728 return 0;
2729}
2730
2731/* Neighbor description. */
2732int
2733peer_description_set (struct peer *peer, char *desc)
2734{
2735 if (peer->desc)
2736 XFREE (MTYPE_PEER_DESC, peer->desc);
2737
2738 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2739
2740 return 0;
2741}
2742
2743int
2744peer_description_unset (struct peer *peer)
2745{
2746 if (peer->desc)
2747 XFREE (MTYPE_PEER_DESC, peer->desc);
2748
2749 peer->desc = NULL;
2750
2751 return 0;
2752}
2753
2754/* Neighbor update-source. */
2755int
paulfd79ac92004-10-13 05:06:08 +00002756peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002757{
2758 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002759 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002760
2761 if (peer->update_if)
2762 {
2763 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2764 && strcmp (peer->update_if, ifname) == 0)
2765 return 0;
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 (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2780 {
2781 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002782 {
2783 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2784 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2785 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2786 }
paul718e3742002-12-13 20:15:29 +00002787 else
2788 BGP_EVENT_ADD (peer, BGP_Stop);
2789 return 0;
2790 }
2791
2792 /* peer-group member updates. */
2793 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002794 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002795 {
2796 if (peer->update_if)
2797 {
2798 if (strcmp (peer->update_if, ifname) == 0)
2799 continue;
2800
2801 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2802 peer->update_if = NULL;
2803 }
2804
2805 if (peer->update_source)
2806 {
2807 sockunion_free (peer->update_source);
2808 peer->update_source = NULL;
2809 }
2810
2811 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2812
2813 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002814 {
2815 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2816 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2817 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2818 }
paul718e3742002-12-13 20:15:29 +00002819 else
2820 BGP_EVENT_ADD (peer, BGP_Stop);
2821 }
2822 return 0;
2823}
2824
2825int
2826peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2827{
2828 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002829 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002830
2831 if (peer->update_source)
2832 {
2833 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2834 && sockunion_cmp (peer->update_source, su) == 0)
2835 return 0;
2836 sockunion_free (peer->update_source);
2837 peer->update_source = NULL;
2838 }
2839
2840 if (peer->update_if)
2841 {
2842 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2843 peer->update_if = NULL;
2844 }
2845
2846 peer->update_source = sockunion_dup (su);
2847
2848 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2849 {
2850 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002851 {
2852 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2853 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2854 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2855 }
paul718e3742002-12-13 20:15:29 +00002856 else
2857 BGP_EVENT_ADD (peer, BGP_Stop);
2858 return 0;
2859 }
2860
2861 /* peer-group member updates. */
2862 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002863 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002864 {
2865 if (peer->update_source)
2866 {
2867 if (sockunion_cmp (peer->update_source, su) == 0)
2868 continue;
2869 sockunion_free (peer->update_source);
2870 peer->update_source = NULL;
2871 }
2872
2873 if (peer->update_if)
2874 {
2875 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2876 peer->update_if = NULL;
2877 }
2878
2879 peer->update_source = sockunion_dup (su);
2880
2881 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002882 {
2883 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2884 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2885 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2886 }
paul718e3742002-12-13 20:15:29 +00002887 else
2888 BGP_EVENT_ADD (peer, BGP_Stop);
2889 }
2890 return 0;
2891}
2892
2893int
2894peer_update_source_unset (struct peer *peer)
2895{
2896 union sockunion *su;
2897 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002898 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002899
2900 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2901 && ! peer->update_source
2902 && ! peer->update_if)
2903 return 0;
2904
2905 if (peer->update_source)
2906 {
2907 sockunion_free (peer->update_source);
2908 peer->update_source = NULL;
2909 }
2910 if (peer->update_if)
2911 {
2912 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2913 peer->update_if = NULL;
2914 }
2915
2916 if (peer_group_active (peer))
2917 {
2918 group = peer->group;
2919
2920 if (group->conf->update_source)
2921 {
2922 su = sockunion_dup (group->conf->update_source);
2923 peer->update_source = su;
2924 }
2925 else if (group->conf->update_if)
2926 peer->update_if =
2927 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2928 }
2929
2930 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2931 {
2932 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002933 {
2934 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2935 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2936 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2937 }
paul718e3742002-12-13 20:15:29 +00002938 else
2939 BGP_EVENT_ADD (peer, BGP_Stop);
2940 return 0;
2941 }
2942
2943 /* peer-group member updates. */
2944 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002945 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002946 {
2947 if (! peer->update_source && ! peer->update_if)
2948 continue;
2949
2950 if (peer->update_source)
2951 {
2952 sockunion_free (peer->update_source);
2953 peer->update_source = NULL;
2954 }
2955
2956 if (peer->update_if)
2957 {
2958 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2959 peer->update_if = NULL;
2960 }
2961
2962 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002963 {
2964 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2965 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2966 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2967 }
paul718e3742002-12-13 20:15:29 +00002968 else
2969 BGP_EVENT_ADD (peer, BGP_Stop);
2970 }
2971 return 0;
2972}
2973
2974int
2975peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002976 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002977{
2978 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002979 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002980
2981 /* Adress family must be activated. */
2982 if (! peer->afc[afi][safi])
2983 return BGP_ERR_PEER_INACTIVE;
2984
2985 /* Default originate can't be used for peer group memeber. */
2986 if (peer_is_group_member (peer, afi, safi))
2987 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2988
2989 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2990 || (rmap && ! peer->default_rmap[afi][safi].name)
2991 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2992 {
2993 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2994
2995 if (rmap)
2996 {
2997 if (peer->default_rmap[afi][safi].name)
2998 free (peer->default_rmap[afi][safi].name);
2999 peer->default_rmap[afi][safi].name = strdup (rmap);
3000 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3001 }
3002 }
3003
3004 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3005 {
3006 if (peer->status == Established && peer->afc_nego[afi][safi])
3007 bgp_default_originate (peer, afi, safi, 0);
3008 return 0;
3009 }
3010
3011 /* peer-group member updates. */
3012 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003013 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003014 {
3015 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3016
3017 if (rmap)
3018 {
3019 if (peer->default_rmap[afi][safi].name)
3020 free (peer->default_rmap[afi][safi].name);
3021 peer->default_rmap[afi][safi].name = strdup (rmap);
3022 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3023 }
3024
3025 if (peer->status == Established && peer->afc_nego[afi][safi])
3026 bgp_default_originate (peer, afi, safi, 0);
3027 }
3028 return 0;
3029}
3030
3031int
3032peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3033{
3034 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003035 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003036
3037 /* Adress family must be activated. */
3038 if (! peer->afc[afi][safi])
3039 return BGP_ERR_PEER_INACTIVE;
3040
3041 /* Default originate can't be used for peer group memeber. */
3042 if (peer_is_group_member (peer, afi, safi))
3043 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3044
3045 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3046 {
3047 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3048
3049 if (peer->default_rmap[afi][safi].name)
3050 free (peer->default_rmap[afi][safi].name);
3051 peer->default_rmap[afi][safi].name = NULL;
3052 peer->default_rmap[afi][safi].map = NULL;
3053 }
3054
3055 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3056 {
3057 if (peer->status == Established && peer->afc_nego[afi][safi])
3058 bgp_default_originate (peer, afi, safi, 1);
3059 return 0;
3060 }
3061
3062 /* peer-group member updates. */
3063 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003064 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003065 {
3066 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3067
3068 if (peer->default_rmap[afi][safi].name)
3069 free (peer->default_rmap[afi][safi].name);
3070 peer->default_rmap[afi][safi].name = NULL;
3071 peer->default_rmap[afi][safi].map = NULL;
3072
3073 if (peer->status == Established && peer->afc_nego[afi][safi])
3074 bgp_default_originate (peer, afi, safi, 1);
3075 }
3076 return 0;
3077}
3078
3079int
3080peer_port_set (struct peer *peer, u_int16_t port)
3081{
3082 peer->port = port;
3083 return 0;
3084}
3085
3086int
3087peer_port_unset (struct peer *peer)
3088{
3089 peer->port = BGP_PORT_DEFAULT;
3090 return 0;
3091}
3092
3093/* neighbor weight. */
3094int
3095peer_weight_set (struct peer *peer, u_int16_t weight)
3096{
3097 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003098 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003099
3100 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3101 peer->weight = weight;
3102
3103 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3104 return 0;
3105
3106 /* peer-group member updates. */
3107 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003108 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003109 {
3110 peer->weight = group->conf->weight;
3111 }
3112 return 0;
3113}
3114
3115int
3116peer_weight_unset (struct peer *peer)
3117{
3118 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003119 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003120
3121 /* Set default weight. */
3122 if (peer_group_active (peer))
3123 peer->weight = peer->group->conf->weight;
3124 else
3125 peer->weight = 0;
3126
3127 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3128
3129 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3130 return 0;
3131
3132 /* peer-group member updates. */
3133 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003134 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003135 {
3136 peer->weight = 0;
3137 }
3138 return 0;
3139}
3140
3141int
3142peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3143{
3144 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003145 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003146
3147 /* Not for peer group memeber. */
3148 if (peer_group_active (peer))
3149 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3150
3151 /* keepalive value check. */
3152 if (keepalive > 65535)
3153 return BGP_ERR_INVALID_VALUE;
3154
3155 /* Holdtime value check. */
3156 if (holdtime > 65535)
3157 return BGP_ERR_INVALID_VALUE;
3158
3159 /* Holdtime value must be either 0 or greater than 3. */
3160 if (holdtime < 3 && holdtime != 0)
3161 return BGP_ERR_INVALID_VALUE;
3162
3163 /* Set value to the configuration. */
3164 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3165 peer->holdtime = holdtime;
3166 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3167
3168 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3169 return 0;
3170
3171 /* peer-group member updates. */
3172 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003173 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003174 {
3175 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3176 peer->holdtime = group->conf->holdtime;
3177 peer->keepalive = group->conf->keepalive;
3178 }
3179 return 0;
3180}
3181
3182int
3183peer_timers_unset (struct peer *peer)
3184{
3185 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003186 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003187
3188 if (peer_group_active (peer))
3189 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3190
3191 /* Clear configuration. */
3192 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3193 peer->keepalive = 0;
3194 peer->holdtime = 0;
3195
3196 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3197 return 0;
3198
3199 /* peer-group member updates. */
3200 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003201 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003202 {
3203 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3204 peer->holdtime = 0;
3205 peer->keepalive = 0;
3206 }
3207
3208 return 0;
3209}
3210
3211int
3212peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3213{
3214 if (peer_group_active (peer))
3215 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3216
3217 if (connect > 65535)
3218 return BGP_ERR_INVALID_VALUE;
3219
3220 /* Set value to the configuration. */
3221 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3222 peer->connect = connect;
3223
3224 /* Set value to timer setting. */
3225 peer->v_connect = connect;
3226
3227 return 0;
3228}
3229
3230int
3231peer_timers_connect_unset (struct peer *peer)
3232{
3233 if (peer_group_active (peer))
3234 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3235
3236 /* Clear configuration. */
3237 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3238 peer->connect = 0;
3239
3240 /* Set timer setting to default value. */
3241 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3242
3243 return 0;
3244}
3245
3246int
3247peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3248{
3249 if (peer_group_active (peer))
3250 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3251
3252 if (routeadv > 600)
3253 return BGP_ERR_INVALID_VALUE;
3254
3255 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3256 peer->routeadv = routeadv;
3257 peer->v_routeadv = routeadv;
3258
3259 return 0;
3260}
3261
3262int
3263peer_advertise_interval_unset (struct peer *peer)
3264{
3265 if (peer_group_active (peer))
3266 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3267
3268 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3269 peer->routeadv = 0;
3270
3271 if (peer_sort (peer) == BGP_PEER_IBGP)
3272 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3273 else
3274 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3275
3276 return 0;
3277}
3278
paul718e3742002-12-13 20:15:29 +00003279/* neighbor interface */
3280int
paulfd79ac92004-10-13 05:06:08 +00003281peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003282{
3283 if (peer->ifname)
3284 free (peer->ifname);
3285 peer->ifname = strdup (str);
3286
3287 return 0;
3288}
3289
3290int
3291peer_interface_unset (struct peer *peer)
3292{
3293 if (peer->ifname)
3294 free (peer->ifname);
3295 peer->ifname = NULL;
3296
3297 return 0;
3298}
3299
3300/* Allow-as in. */
3301int
3302peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3303{
3304 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003305 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003306
3307 if (allow_num < 1 || allow_num > 10)
3308 return BGP_ERR_INVALID_VALUE;
3309
3310 if (peer->allowas_in[afi][safi] != allow_num)
3311 {
3312 peer->allowas_in[afi][safi] = allow_num;
3313 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3314 peer_change_action (peer, afi, safi, peer_change_reset_in);
3315 }
3316
3317 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3318 return 0;
3319
3320 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003321 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003322 {
3323 if (peer->allowas_in[afi][safi] != allow_num)
3324 {
3325 peer->allowas_in[afi][safi] = allow_num;
3326 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3327 peer_change_action (peer, afi, safi, peer_change_reset_in);
3328 }
3329
3330 }
3331 return 0;
3332}
3333
3334int
3335peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3336{
3337 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003338 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003339
3340 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3341 {
3342 peer->allowas_in[afi][safi] = 0;
3343 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3344 }
3345
3346 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3347 return 0;
3348
3349 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003350 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003351 {
3352 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3353 {
3354 peer->allowas_in[afi][safi] = 0;
3355 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3356 }
3357 }
3358 return 0;
3359}
3360
3361int
3362peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3363{
3364 struct bgp *bgp = peer->bgp;
3365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003367
3368 if (peer_sort (peer) != BGP_PEER_EBGP
3369 && peer_sort (peer) != BGP_PEER_INTERNAL)
3370 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3371
3372 if (bgp->as == as)
3373 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3374
3375 if (peer_group_active (peer))
3376 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3377
3378 if (peer->change_local_as == as &&
3379 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3380 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3381 return 0;
3382
3383 peer->change_local_as = as;
3384 if (no_prepend)
3385 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3386 else
3387 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3388
3389 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3390 {
3391 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003392 {
3393 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3394 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3395 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3396 }
paul718e3742002-12-13 20:15:29 +00003397 else
3398 BGP_EVENT_ADD (peer, BGP_Stop);
3399
3400 return 0;
3401 }
3402
3403 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003404 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003405 {
3406 peer->change_local_as = as;
3407 if (no_prepend)
3408 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3409 else
3410 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3411
3412 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003413 {
3414 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3415 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3416 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3417 }
paul718e3742002-12-13 20:15:29 +00003418 else
3419 BGP_EVENT_ADD (peer, BGP_Stop);
3420 }
3421
3422 return 0;
3423}
3424
3425int
3426peer_local_as_unset (struct peer *peer)
3427{
3428 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003429 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003430
3431 if (peer_group_active (peer))
3432 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3433
3434 if (! peer->change_local_as)
3435 return 0;
3436
3437 peer->change_local_as = 0;
3438 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3439
3440 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3441 {
3442 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003443 {
3444 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3445 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3446 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3447 }
paul718e3742002-12-13 20:15:29 +00003448 else
3449 BGP_EVENT_ADD (peer, BGP_Stop);
3450
3451 return 0;
3452 }
3453
3454 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003455 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003456 {
3457 peer->change_local_as = 0;
3458 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3459
3460 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003461 {
3462 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3463 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3464 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3465 }
paul718e3742002-12-13 20:15:29 +00003466 else
3467 BGP_EVENT_ADD (peer, BGP_Stop);
3468 }
3469 return 0;
3470}
3471
Paul Jakma0df7c912008-07-21 21:02:49 +00003472/* Set password for authenticating with the peer. */
3473int
3474peer_password_set (struct peer *peer, const char *password)
3475{
3476 struct listnode *nn, *nnode;
3477 int len = password ? strlen(password) : 0;
3478 int ret = BGP_SUCCESS;
3479
3480 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3481 return BGP_ERR_INVALID_VALUE;
3482
3483 if (peer->password && strcmp (peer->password, password) == 0
3484 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3485 return 0;
3486
3487 if (peer->password)
3488 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3489
3490 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3491
3492 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3493 {
3494 if (peer->status == Established)
3495 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3496 else
3497 BGP_EVENT_ADD (peer, BGP_Stop);
3498
3499 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3500 }
3501
3502 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3503 {
3504 if (peer->password && strcmp (peer->password, password) == 0)
3505 continue;
3506
3507 if (peer->password)
3508 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3509
3510 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3511
3512 if (peer->status == Established)
3513 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3514 else
3515 BGP_EVENT_ADD (peer, BGP_Stop);
3516
3517 if (bgp_md5_set (peer) < 0)
3518 ret = BGP_ERR_TCPSIG_FAILED;
3519 }
3520
3521 return ret;
3522}
3523
3524int
3525peer_password_unset (struct peer *peer)
3526{
3527 struct listnode *nn, *nnode;
3528
3529 if (!peer->password
3530 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3531 return 0;
3532
3533 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3534 {
3535 if (peer_group_active (peer)
3536 && peer->group->conf->password
3537 && strcmp (peer->group->conf->password, peer->password) == 0)
3538 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3539
3540 if (peer->status == Established)
3541 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3542 else
3543 BGP_EVENT_ADD (peer, BGP_Stop);
3544
3545 if (peer->password)
3546 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3547
3548 peer->password = NULL;
3549
3550 bgp_md5_set (peer);
3551
3552 return 0;
3553 }
3554
3555 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3556 peer->password = NULL;
3557
3558 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3559 {
3560 if (!peer->password)
3561 continue;
3562
3563 if (peer->status == Established)
3564 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3565 else
3566 BGP_EVENT_ADD (peer, BGP_Stop);
3567
3568 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3569 peer->password = NULL;
3570
3571 bgp_md5_set (peer);
3572 }
3573
3574 return 0;
3575}
3576
paul718e3742002-12-13 20:15:29 +00003577/* Set distribute list to the peer. */
3578int
3579peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003580 const char *name)
paul718e3742002-12-13 20:15:29 +00003581{
3582 struct bgp_filter *filter;
3583 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003584 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003585
3586 if (! peer->afc[afi][safi])
3587 return BGP_ERR_PEER_INACTIVE;
3588
3589 if (direct != FILTER_IN && direct != FILTER_OUT)
3590 return BGP_ERR_INVALID_VALUE;
3591
3592 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3593 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3594
3595 filter = &peer->filter[afi][safi];
3596
3597 if (filter->plist[direct].name)
3598 return BGP_ERR_PEER_FILTER_CONFLICT;
3599
3600 if (filter->dlist[direct].name)
3601 free (filter->dlist[direct].name);
3602 filter->dlist[direct].name = strdup (name);
3603 filter->dlist[direct].alist = access_list_lookup (afi, name);
3604
3605 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3606 return 0;
3607
3608 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003609 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003610 {
3611 filter = &peer->filter[afi][safi];
3612
3613 if (! peer->af_group[afi][safi])
3614 continue;
3615
3616 if (filter->dlist[direct].name)
3617 free (filter->dlist[direct].name);
3618 filter->dlist[direct].name = strdup (name);
3619 filter->dlist[direct].alist = access_list_lookup (afi, name);
3620 }
3621
3622 return 0;
3623}
3624
3625int
3626peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3627{
3628 struct bgp_filter *filter;
3629 struct bgp_filter *gfilter;
3630 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003631 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003632
3633 if (! peer->afc[afi][safi])
3634 return BGP_ERR_PEER_INACTIVE;
3635
3636 if (direct != FILTER_IN && direct != FILTER_OUT)
3637 return BGP_ERR_INVALID_VALUE;
3638
3639 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3640 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3641
3642 filter = &peer->filter[afi][safi];
3643
3644 /* apply peer-group filter */
3645 if (peer->af_group[afi][safi])
3646 {
3647 gfilter = &peer->group->conf->filter[afi][safi];
3648
3649 if (gfilter->dlist[direct].name)
3650 {
3651 if (filter->dlist[direct].name)
3652 free (filter->dlist[direct].name);
3653 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3654 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3655 return 0;
3656 }
3657 }
3658
3659 if (filter->dlist[direct].name)
3660 free (filter->dlist[direct].name);
3661 filter->dlist[direct].name = NULL;
3662 filter->dlist[direct].alist = NULL;
3663
3664 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3665 return 0;
3666
3667 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003668 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003669 {
3670 filter = &peer->filter[afi][safi];
3671
3672 if (! peer->af_group[afi][safi])
3673 continue;
3674
3675 if (filter->dlist[direct].name)
3676 free (filter->dlist[direct].name);
3677 filter->dlist[direct].name = NULL;
3678 filter->dlist[direct].alist = NULL;
3679 }
3680
3681 return 0;
3682}
3683
3684/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003685static void
paul718e3742002-12-13 20:15:29 +00003686peer_distribute_update (struct access_list *access)
3687{
3688 afi_t afi;
3689 safi_t safi;
3690 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003691 struct listnode *mnode, *mnnode;
3692 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003693 struct bgp *bgp;
3694 struct peer *peer;
3695 struct peer_group *group;
3696 struct bgp_filter *filter;
3697
paul1eb8ef22005-04-07 07:30:20 +00003698 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003699 {
paul1eb8ef22005-04-07 07:30:20 +00003700 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003701 {
3702 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3703 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3704 {
3705 filter = &peer->filter[afi][safi];
3706
3707 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3708 {
3709 if (filter->dlist[direct].name)
3710 filter->dlist[direct].alist =
3711 access_list_lookup (afi, filter->dlist[direct].name);
3712 else
3713 filter->dlist[direct].alist = NULL;
3714 }
3715 }
3716 }
paul1eb8ef22005-04-07 07:30:20 +00003717 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003718 {
3719 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3720 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3721 {
3722 filter = &group->conf->filter[afi][safi];
3723
3724 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3725 {
3726 if (filter->dlist[direct].name)
3727 filter->dlist[direct].alist =
3728 access_list_lookup (afi, filter->dlist[direct].name);
3729 else
3730 filter->dlist[direct].alist = NULL;
3731 }
3732 }
3733 }
3734 }
3735}
3736
3737/* Set prefix list to the peer. */
3738int
3739peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003740 const char *name)
paul718e3742002-12-13 20:15:29 +00003741{
3742 struct bgp_filter *filter;
3743 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003744 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003745
3746 if (! peer->afc[afi][safi])
3747 return BGP_ERR_PEER_INACTIVE;
3748
3749 if (direct != FILTER_IN && direct != FILTER_OUT)
3750 return BGP_ERR_INVALID_VALUE;
3751
3752 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3753 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3754
3755 filter = &peer->filter[afi][safi];
3756
3757 if (filter->dlist[direct].name)
3758 return BGP_ERR_PEER_FILTER_CONFLICT;
3759
3760 if (filter->plist[direct].name)
3761 free (filter->plist[direct].name);
3762 filter->plist[direct].name = strdup (name);
3763 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3764
3765 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3766 return 0;
3767
3768 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003769 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003770 {
3771 filter = &peer->filter[afi][safi];
3772
3773 if (! peer->af_group[afi][safi])
3774 continue;
3775
3776 if (filter->plist[direct].name)
3777 free (filter->plist[direct].name);
3778 filter->plist[direct].name = strdup (name);
3779 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3780 }
3781 return 0;
3782}
3783
3784int
3785peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3786{
3787 struct bgp_filter *filter;
3788 struct bgp_filter *gfilter;
3789 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003790 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003791
3792 if (! peer->afc[afi][safi])
3793 return BGP_ERR_PEER_INACTIVE;
3794
3795 if (direct != FILTER_IN && direct != FILTER_OUT)
3796 return BGP_ERR_INVALID_VALUE;
3797
3798 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3799 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3800
3801 filter = &peer->filter[afi][safi];
3802
3803 /* apply peer-group filter */
3804 if (peer->af_group[afi][safi])
3805 {
3806 gfilter = &peer->group->conf->filter[afi][safi];
3807
3808 if (gfilter->plist[direct].name)
3809 {
3810 if (filter->plist[direct].name)
3811 free (filter->plist[direct].name);
3812 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3813 filter->plist[direct].plist = gfilter->plist[direct].plist;
3814 return 0;
3815 }
3816 }
3817
3818 if (filter->plist[direct].name)
3819 free (filter->plist[direct].name);
3820 filter->plist[direct].name = NULL;
3821 filter->plist[direct].plist = NULL;
3822
3823 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3824 return 0;
3825
3826 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003827 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003828 {
3829 filter = &peer->filter[afi][safi];
3830
3831 if (! peer->af_group[afi][safi])
3832 continue;
3833
3834 if (filter->plist[direct].name)
3835 free (filter->plist[direct].name);
3836 filter->plist[direct].name = NULL;
3837 filter->plist[direct].plist = NULL;
3838 }
3839
3840 return 0;
3841}
3842
3843/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003844static void
paul718e3742002-12-13 20:15:29 +00003845peer_prefix_list_update (struct prefix_list *plist)
3846{
paul1eb8ef22005-04-07 07:30:20 +00003847 struct listnode *mnode, *mnnode;
3848 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003849 struct bgp *bgp;
3850 struct peer *peer;
3851 struct peer_group *group;
3852 struct bgp_filter *filter;
3853 afi_t afi;
3854 safi_t safi;
3855 int direct;
3856
paul1eb8ef22005-04-07 07:30:20 +00003857 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003858 {
paul1eb8ef22005-04-07 07:30:20 +00003859 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003860 {
3861 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3862 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3863 {
3864 filter = &peer->filter[afi][safi];
3865
3866 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3867 {
3868 if (filter->plist[direct].name)
3869 filter->plist[direct].plist =
3870 prefix_list_lookup (afi, filter->plist[direct].name);
3871 else
3872 filter->plist[direct].plist = NULL;
3873 }
3874 }
3875 }
paul1eb8ef22005-04-07 07:30:20 +00003876 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003877 {
3878 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3879 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3880 {
3881 filter = &group->conf->filter[afi][safi];
3882
3883 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3884 {
3885 if (filter->plist[direct].name)
3886 filter->plist[direct].plist =
3887 prefix_list_lookup (afi, filter->plist[direct].name);
3888 else
3889 filter->plist[direct].plist = NULL;
3890 }
3891 }
3892 }
3893 }
3894}
3895
3896int
3897peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003898 const char *name)
paul718e3742002-12-13 20:15:29 +00003899{
3900 struct bgp_filter *filter;
3901 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003902 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003903
3904 if (! peer->afc[afi][safi])
3905 return BGP_ERR_PEER_INACTIVE;
3906
3907 if (direct != FILTER_IN && direct != FILTER_OUT)
3908 return BGP_ERR_INVALID_VALUE;
3909
3910 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3911 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3912
3913 filter = &peer->filter[afi][safi];
3914
3915 if (filter->aslist[direct].name)
3916 free (filter->aslist[direct].name);
3917 filter->aslist[direct].name = strdup (name);
3918 filter->aslist[direct].aslist = as_list_lookup (name);
3919
3920 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3921 return 0;
3922
3923 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003924 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003925 {
3926 filter = &peer->filter[afi][safi];
3927
3928 if (! peer->af_group[afi][safi])
3929 continue;
3930
3931 if (filter->aslist[direct].name)
3932 free (filter->aslist[direct].name);
3933 filter->aslist[direct].name = strdup (name);
3934 filter->aslist[direct].aslist = as_list_lookup (name);
3935 }
3936 return 0;
3937}
3938
3939int
3940peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3941{
3942 struct bgp_filter *filter;
3943 struct bgp_filter *gfilter;
3944 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003945 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003946
3947 if (! peer->afc[afi][safi])
3948 return BGP_ERR_PEER_INACTIVE;
3949
hassob5f29602005-05-25 21:00:28 +00003950 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003951 return BGP_ERR_INVALID_VALUE;
3952
hassob5f29602005-05-25 21:00:28 +00003953 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003954 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3955
3956 filter = &peer->filter[afi][safi];
3957
3958 /* apply peer-group filter */
3959 if (peer->af_group[afi][safi])
3960 {
3961 gfilter = &peer->group->conf->filter[afi][safi];
3962
3963 if (gfilter->aslist[direct].name)
3964 {
3965 if (filter->aslist[direct].name)
3966 free (filter->aslist[direct].name);
3967 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3968 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3969 return 0;
3970 }
3971 }
3972
3973 if (filter->aslist[direct].name)
3974 free (filter->aslist[direct].name);
3975 filter->aslist[direct].name = NULL;
3976 filter->aslist[direct].aslist = NULL;
3977
3978 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3979 return 0;
3980
3981 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003982 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003983 {
3984 filter = &peer->filter[afi][safi];
3985
3986 if (! peer->af_group[afi][safi])
3987 continue;
3988
3989 if (filter->aslist[direct].name)
3990 free (filter->aslist[direct].name);
3991 filter->aslist[direct].name = NULL;
3992 filter->aslist[direct].aslist = NULL;
3993 }
3994
3995 return 0;
3996}
3997
paul94f2b392005-06-28 12:44:16 +00003998static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003999peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004000{
4001 afi_t afi;
4002 safi_t safi;
4003 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004004 struct listnode *mnode, *mnnode;
4005 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004006 struct bgp *bgp;
4007 struct peer *peer;
4008 struct peer_group *group;
4009 struct bgp_filter *filter;
4010
paul1eb8ef22005-04-07 07:30:20 +00004011 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004012 {
paul1eb8ef22005-04-07 07:30:20 +00004013 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004014 {
4015 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4016 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4017 {
4018 filter = &peer->filter[afi][safi];
4019
4020 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4021 {
4022 if (filter->aslist[direct].name)
4023 filter->aslist[direct].aslist =
4024 as_list_lookup (filter->aslist[direct].name);
4025 else
4026 filter->aslist[direct].aslist = NULL;
4027 }
4028 }
4029 }
paul1eb8ef22005-04-07 07:30:20 +00004030 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004031 {
4032 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4033 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4034 {
4035 filter = &group->conf->filter[afi][safi];
4036
4037 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4038 {
4039 if (filter->aslist[direct].name)
4040 filter->aslist[direct].aslist =
4041 as_list_lookup (filter->aslist[direct].name);
4042 else
4043 filter->aslist[direct].aslist = NULL;
4044 }
4045 }
4046 }
4047 }
4048}
4049
4050/* Set route-map to the peer. */
4051int
4052peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004053 const char *name)
paul718e3742002-12-13 20:15:29 +00004054{
4055 struct bgp_filter *filter;
4056 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004057 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004058
4059 if (! peer->afc[afi][safi])
4060 return BGP_ERR_PEER_INACTIVE;
4061
paulfee0f4c2004-09-13 05:12:46 +00004062 if (direct != RMAP_IN && direct != RMAP_OUT &&
4063 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004064 return BGP_ERR_INVALID_VALUE;
4065
paulfee0f4c2004-09-13 05:12:46 +00004066 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4067 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004068 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4069
4070 filter = &peer->filter[afi][safi];
4071
4072 if (filter->map[direct].name)
4073 free (filter->map[direct].name);
4074
4075 filter->map[direct].name = strdup (name);
4076 filter->map[direct].map = route_map_lookup_by_name (name);
4077
4078 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4079 return 0;
4080
4081 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004082 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004083 {
4084 filter = &peer->filter[afi][safi];
4085
4086 if (! peer->af_group[afi][safi])
4087 continue;
4088
4089 if (filter->map[direct].name)
4090 free (filter->map[direct].name);
4091 filter->map[direct].name = strdup (name);
4092 filter->map[direct].map = route_map_lookup_by_name (name);
4093 }
4094 return 0;
4095}
4096
4097/* Unset route-map from the peer. */
4098int
4099peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4100{
4101 struct bgp_filter *filter;
4102 struct bgp_filter *gfilter;
4103 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004104 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004105
4106 if (! peer->afc[afi][safi])
4107 return BGP_ERR_PEER_INACTIVE;
4108
hassob5f29602005-05-25 21:00:28 +00004109 if (direct != RMAP_IN && direct != RMAP_OUT &&
4110 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004111 return BGP_ERR_INVALID_VALUE;
4112
hassob5f29602005-05-25 21:00:28 +00004113 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4114 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004115 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4116
4117 filter = &peer->filter[afi][safi];
4118
4119 /* apply peer-group filter */
4120 if (peer->af_group[afi][safi])
4121 {
4122 gfilter = &peer->group->conf->filter[afi][safi];
4123
4124 if (gfilter->map[direct].name)
4125 {
4126 if (filter->map[direct].name)
4127 free (filter->map[direct].name);
4128 filter->map[direct].name = strdup (gfilter->map[direct].name);
4129 filter->map[direct].map = gfilter->map[direct].map;
4130 return 0;
4131 }
4132 }
4133
4134 if (filter->map[direct].name)
4135 free (filter->map[direct].name);
4136 filter->map[direct].name = NULL;
4137 filter->map[direct].map = NULL;
4138
4139 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4140 return 0;
4141
4142 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004143 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004144 {
4145 filter = &peer->filter[afi][safi];
4146
4147 if (! peer->af_group[afi][safi])
4148 continue;
4149
4150 if (filter->map[direct].name)
4151 free (filter->map[direct].name);
4152 filter->map[direct].name = NULL;
4153 filter->map[direct].map = NULL;
4154 }
4155 return 0;
4156}
4157
4158/* Set unsuppress-map to the peer. */
4159int
paulfd79ac92004-10-13 05:06:08 +00004160peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4161 const char *name)
paul718e3742002-12-13 20:15:29 +00004162{
4163 struct bgp_filter *filter;
4164 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004165 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004166
4167 if (! peer->afc[afi][safi])
4168 return BGP_ERR_PEER_INACTIVE;
4169
4170 if (peer_is_group_member (peer, afi, safi))
4171 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4172
4173 filter = &peer->filter[afi][safi];
4174
4175 if (filter->usmap.name)
4176 free (filter->usmap.name);
4177
4178 filter->usmap.name = strdup (name);
4179 filter->usmap.map = route_map_lookup_by_name (name);
4180
4181 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4182 return 0;
4183
4184 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004185 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004186 {
4187 filter = &peer->filter[afi][safi];
4188
4189 if (! peer->af_group[afi][safi])
4190 continue;
4191
4192 if (filter->usmap.name)
4193 free (filter->usmap.name);
4194 filter->usmap.name = strdup (name);
4195 filter->usmap.map = route_map_lookup_by_name (name);
4196 }
4197 return 0;
4198}
4199
4200/* Unset route-map from the peer. */
4201int
4202peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4203{
4204 struct bgp_filter *filter;
4205 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004206 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004207
4208 if (! peer->afc[afi][safi])
4209 return BGP_ERR_PEER_INACTIVE;
4210
4211 if (peer_is_group_member (peer, afi, safi))
4212 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4213
4214 filter = &peer->filter[afi][safi];
4215
4216 if (filter->usmap.name)
4217 free (filter->usmap.name);
4218 filter->usmap.name = NULL;
4219 filter->usmap.map = NULL;
4220
4221 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4222 return 0;
4223
4224 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004225 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004226 {
4227 filter = &peer->filter[afi][safi];
4228
4229 if (! peer->af_group[afi][safi])
4230 continue;
4231
4232 if (filter->usmap.name)
4233 free (filter->usmap.name);
4234 filter->usmap.name = NULL;
4235 filter->usmap.map = NULL;
4236 }
4237 return 0;
4238}
4239
4240int
4241peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004242 u_int32_t max, u_char threshold,
4243 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004244{
4245 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004246 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004247
4248 if (! peer->afc[afi][safi])
4249 return BGP_ERR_PEER_INACTIVE;
4250
4251 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4252 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004253 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004254 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004255 if (warning)
4256 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4257 else
4258 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4259
4260 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4261 return 0;
4262
4263 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004264 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004265 {
4266 if (! peer->af_group[afi][safi])
4267 continue;
4268
4269 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4270 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004271 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004272 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004273 if (warning)
4274 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4275 else
4276 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4277 }
4278 return 0;
4279}
4280
4281int
4282peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4283{
4284 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004285 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004286
4287 if (! peer->afc[afi][safi])
4288 return BGP_ERR_PEER_INACTIVE;
4289
4290 /* apply peer-group config */
4291 if (peer->af_group[afi][safi])
4292 {
4293 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4294 PEER_FLAG_MAX_PREFIX))
4295 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4296 else
4297 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4298
4299 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4300 PEER_FLAG_MAX_PREFIX_WARNING))
4301 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4302 else
4303 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4304
4305 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004306 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004307 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004308 return 0;
4309 }
4310
4311 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4312 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4313 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004314 peer->pmax_threshold[afi][safi] = 0;
4315 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004316
4317 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4318 return 0;
4319
4320 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004321 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004322 {
4323 if (! peer->af_group[afi][safi])
4324 continue;
4325
4326 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4327 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4328 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004329 peer->pmax_threshold[afi][safi] = 0;
4330 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004331 }
4332 return 0;
4333}
4334
4335int
4336peer_clear (struct peer *peer)
4337{
4338 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4339 {
hasso0a486e52005-02-01 20:57:17 +00004340 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4341 {
4342 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4343 if (peer->t_pmax_restart)
4344 {
4345 BGP_TIMER_OFF (peer->t_pmax_restart);
4346 if (BGP_DEBUG (events, EVENTS))
4347 zlog_debug ("%s Maximum-prefix restart timer canceled",
4348 peer->host);
4349 }
4350 BGP_EVENT_ADD (peer, BGP_Start);
4351 return 0;
4352 }
4353
paul718e3742002-12-13 20:15:29 +00004354 peer->v_start = BGP_INIT_START_TIMER;
4355 if (peer->status == Established)
4356 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4357 BGP_NOTIFY_CEASE_ADMIN_RESET);
4358 else
4359 BGP_EVENT_ADD (peer, BGP_Stop);
4360 }
4361 return 0;
4362}
4363
4364int
4365peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4366 enum bgp_clear_type stype)
4367{
4368 if (peer->status != Established)
4369 return 0;
4370
4371 if (! peer->afc[afi][safi])
4372 return BGP_ERR_AF_UNCONFIGURED;
4373
paulfee0f4c2004-09-13 05:12:46 +00004374 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4375 {
4376 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4377 return 0;
4378 bgp_check_local_routes_rsclient (peer, afi, safi);
4379 bgp_soft_reconfig_rsclient (peer, afi, safi);
4380 }
4381
paul718e3742002-12-13 20:15:29 +00004382 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4383 bgp_announce_route (peer, afi, safi);
4384
4385 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4386 {
4387 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4388 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4389 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4390 {
4391 struct bgp_filter *filter = &peer->filter[afi][safi];
4392 u_char prefix_type;
4393
4394 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4395 prefix_type = ORF_TYPE_PREFIX;
4396 else
4397 prefix_type = ORF_TYPE_PREFIX_OLD;
4398
4399 if (filter->plist[FILTER_IN].plist)
4400 {
4401 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4402 bgp_route_refresh_send (peer, afi, safi,
4403 prefix_type, REFRESH_DEFER, 1);
4404 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4405 REFRESH_IMMEDIATE, 0);
4406 }
4407 else
4408 {
4409 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4410 bgp_route_refresh_send (peer, afi, safi,
4411 prefix_type, REFRESH_IMMEDIATE, 1);
4412 else
4413 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4414 }
4415 return 0;
4416 }
4417 }
4418
4419 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4420 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4421 {
4422 /* If neighbor has soft reconfiguration inbound flag.
4423 Use Adj-RIB-In database. */
4424 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4425 bgp_soft_reconfig_in (peer, afi, safi);
4426 else
4427 {
4428 /* If neighbor has route refresh capability, send route refresh
4429 message to the peer. */
4430 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4431 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4432 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4433 else
4434 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4435 }
4436 }
4437 return 0;
4438}
4439
paulfd79ac92004-10-13 05:06:08 +00004440/* Display peer uptime.*/
4441/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004442char *
4443peer_uptime (time_t uptime2, char *buf, size_t len)
4444{
4445 time_t uptime1;
4446 struct tm *tm;
4447
4448 /* Check buffer length. */
4449 if (len < BGP_UPTIME_LEN)
4450 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004451 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004452 /* XXX: should return status instead of buf... */
4453 snprintf (buf, len, "<error> ");
4454 return buf;
paul718e3742002-12-13 20:15:29 +00004455 }
4456
4457 /* If there is no connection has been done before print `never'. */
4458 if (uptime2 == 0)
4459 {
4460 snprintf (buf, len, "never ");
4461 return buf;
4462 }
4463
4464 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004465 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004466 uptime1 -= uptime2;
4467 tm = gmtime (&uptime1);
4468
4469 /* Making formatted timer strings. */
4470#define ONE_DAY_SECOND 60*60*24
4471#define ONE_WEEK_SECOND 60*60*24*7
4472
4473 if (uptime1 < ONE_DAY_SECOND)
4474 snprintf (buf, len, "%02d:%02d:%02d",
4475 tm->tm_hour, tm->tm_min, tm->tm_sec);
4476 else if (uptime1 < ONE_WEEK_SECOND)
4477 snprintf (buf, len, "%dd%02dh%02dm",
4478 tm->tm_yday, tm->tm_hour, tm->tm_min);
4479 else
4480 snprintf (buf, len, "%02dw%dd%02dh",
4481 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4482 return buf;
4483}
4484
paul94f2b392005-06-28 12:44:16 +00004485static void
paul718e3742002-12-13 20:15:29 +00004486bgp_config_write_filter (struct vty *vty, struct peer *peer,
4487 afi_t afi, safi_t safi)
4488{
4489 struct bgp_filter *filter;
4490 struct bgp_filter *gfilter = NULL;
4491 char *addr;
4492 int in = FILTER_IN;
4493 int out = FILTER_OUT;
4494
4495 addr = peer->host;
4496 filter = &peer->filter[afi][safi];
4497 if (peer->af_group[afi][safi])
4498 gfilter = &peer->group->conf->filter[afi][safi];
4499
4500 /* distribute-list. */
4501 if (filter->dlist[in].name)
4502 if (! gfilter || ! gfilter->dlist[in].name
4503 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4504 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4505 filter->dlist[in].name, VTY_NEWLINE);
4506 if (filter->dlist[out].name && ! gfilter)
4507 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4508 filter->dlist[out].name, VTY_NEWLINE);
4509
4510 /* prefix-list. */
4511 if (filter->plist[in].name)
4512 if (! gfilter || ! gfilter->plist[in].name
4513 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4514 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4515 filter->plist[in].name, VTY_NEWLINE);
4516 if (filter->plist[out].name && ! gfilter)
4517 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4518 filter->plist[out].name, VTY_NEWLINE);
4519
4520 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004521 if (filter->map[RMAP_IN].name)
4522 if (! gfilter || ! gfilter->map[RMAP_IN].name
4523 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004524 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004525 filter->map[RMAP_IN].name, VTY_NEWLINE);
4526 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004527 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004528 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4529 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4530 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4531 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4532 if (filter->map[RMAP_EXPORT].name)
4533 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4534 || strcmp (filter->map[RMAP_EXPORT].name,
4535 gfilter->map[RMAP_EXPORT].name) != 0)
4536 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4537 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004538
4539 /* unsuppress-map */
4540 if (filter->usmap.name && ! gfilter)
4541 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4542 filter->usmap.name, VTY_NEWLINE);
4543
4544 /* filter-list. */
4545 if (filter->aslist[in].name)
4546 if (! gfilter || ! gfilter->aslist[in].name
4547 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4548 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4549 filter->aslist[in].name, VTY_NEWLINE);
4550 if (filter->aslist[out].name && ! gfilter)
4551 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4552 filter->aslist[out].name, VTY_NEWLINE);
4553}
4554
4555/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004556static void
paul718e3742002-12-13 20:15:29 +00004557bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4558 struct peer *peer, afi_t afi, safi_t safi)
4559{
4560 struct bgp_filter *filter;
4561 struct peer *g_peer = NULL;
4562 char buf[SU_ADDRSTRLEN];
4563 char *addr;
4564
4565 filter = &peer->filter[afi][safi];
4566 addr = peer->host;
4567 if (peer_group_active (peer))
4568 g_peer = peer->group->conf;
4569
4570 /************************************
4571 ****** Global to the neighbor ******
4572 ************************************/
4573 if (afi == AFI_IP && safi == SAFI_UNICAST)
4574 {
4575 /* remote-as. */
4576 if (! peer_group_active (peer))
4577 {
4578 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4579 vty_out (vty, " neighbor %s peer-group%s", addr,
4580 VTY_NEWLINE);
4581 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004582 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004583 VTY_NEWLINE);
4584 }
4585 else
4586 {
4587 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004588 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004589 VTY_NEWLINE);
4590 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4591 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4592 peer->group->name, VTY_NEWLINE);
4593 }
4594
4595 /* local-as. */
4596 if (peer->change_local_as)
4597 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004598 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004599 peer->change_local_as,
4600 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4601 " no-prepend" : "", VTY_NEWLINE);
4602
4603 /* Description. */
4604 if (peer->desc)
4605 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4606 VTY_NEWLINE);
4607
4608 /* Shutdown. */
4609 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4610 if (! peer_group_active (peer) ||
4611 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4612 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4613
Paul Jakma0df7c912008-07-21 21:02:49 +00004614 /* Password. */
4615 if (peer->password)
4616 if (!peer_group_active (peer)
4617 || ! g_peer->password
4618 || strcmp (peer->password, g_peer->password) != 0)
4619 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4620 VTY_NEWLINE);
4621
paul718e3742002-12-13 20:15:29 +00004622 /* BGP port. */
4623 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004624 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004625 VTY_NEWLINE);
4626
4627 /* Local interface name. */
4628 if (peer->ifname)
4629 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4630 VTY_NEWLINE);
4631
4632 /* Passive. */
4633 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4634 if (! peer_group_active (peer) ||
4635 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4636 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4637
4638 /* EBGP multihop. */
4639 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4640 if (! peer_group_active (peer) ||
4641 g_peer->ttl != peer->ttl)
4642 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4643 VTY_NEWLINE);
4644
hasso6ffd2072005-02-02 14:50:11 +00004645 /* disable-connected-check. */
4646 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004647 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004648 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4649 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004650
4651 /* Update-source. */
4652 if (peer->update_if)
4653 if (! peer_group_active (peer) || ! g_peer->update_if
4654 || strcmp (g_peer->update_if, peer->update_if) != 0)
4655 vty_out (vty, " neighbor %s update-source %s%s", addr,
4656 peer->update_if, VTY_NEWLINE);
4657 if (peer->update_source)
4658 if (! peer_group_active (peer) || ! g_peer->update_source
4659 || sockunion_cmp (g_peer->update_source,
4660 peer->update_source) != 0)
4661 vty_out (vty, " neighbor %s update-source %s%s", addr,
4662 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4663 VTY_NEWLINE);
4664
paul718e3742002-12-13 20:15:29 +00004665 /* advertisement-interval */
4666 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4667 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4668 addr, peer->v_routeadv, VTY_NEWLINE);
4669
4670 /* timers. */
4671 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4672 && ! peer_group_active (peer))
4673 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4674 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4675
4676 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4677 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4678 peer->connect, VTY_NEWLINE);
4679
4680 /* Default weight. */
4681 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4682 if (! peer_group_active (peer) ||
4683 g_peer->weight != peer->weight)
4684 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4685 VTY_NEWLINE);
4686
paul718e3742002-12-13 20:15:29 +00004687 /* Dynamic capability. */
4688 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4689 if (! peer_group_active (peer) ||
4690 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4691 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4692 VTY_NEWLINE);
4693
4694 /* dont capability negotiation. */
4695 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4696 if (! peer_group_active (peer) ||
4697 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4698 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4699 VTY_NEWLINE);
4700
4701 /* override capability negotiation. */
4702 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4703 if (! peer_group_active (peer) ||
4704 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4705 vty_out (vty, " neighbor %s override-capability%s", addr,
4706 VTY_NEWLINE);
4707
4708 /* strict capability negotiation. */
4709 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4710 if (! peer_group_active (peer) ||
4711 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4712 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4713 VTY_NEWLINE);
4714
4715 if (! peer_group_active (peer))
4716 {
4717 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4718 {
4719 if (peer->afc[AFI_IP][SAFI_UNICAST])
4720 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4721 }
4722 else
4723 {
4724 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4725 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4726 }
4727 }
4728 }
4729
4730
4731 /************************************
4732 ****** Per AF to the neighbor ******
4733 ************************************/
4734
4735 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4736 {
4737 if (peer->af_group[afi][safi])
4738 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4739 peer->group->name, VTY_NEWLINE);
4740 else
4741 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4742 }
4743
4744 /* ORF capability. */
4745 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4746 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4747 if (! peer->af_group[afi][safi])
4748 {
4749 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4750
4751 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4752 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4753 vty_out (vty, " both");
4754 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4755 vty_out (vty, " send");
4756 else
4757 vty_out (vty, " receive");
4758 vty_out (vty, "%s", VTY_NEWLINE);
4759 }
4760
4761 /* Route reflector client. */
4762 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4763 && ! peer->af_group[afi][safi])
4764 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4765 VTY_NEWLINE);
4766
4767 /* Nexthop self. */
4768 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4769 && ! peer->af_group[afi][safi])
4770 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4771
4772 /* Remove private AS. */
4773 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4774 && ! peer->af_group[afi][safi])
4775 vty_out (vty, " neighbor %s remove-private-AS%s",
4776 addr, VTY_NEWLINE);
4777
4778 /* send-community print. */
4779 if (! peer->af_group[afi][safi])
4780 {
4781 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4782 {
4783 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4784 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4785 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4786 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4787 vty_out (vty, " neighbor %s send-community extended%s",
4788 addr, VTY_NEWLINE);
4789 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4790 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4791 }
4792 else
4793 {
4794 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4795 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4796 vty_out (vty, " no neighbor %s send-community both%s",
4797 addr, VTY_NEWLINE);
4798 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4799 vty_out (vty, " no neighbor %s send-community extended%s",
4800 addr, VTY_NEWLINE);
4801 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4802 vty_out (vty, " no neighbor %s send-community%s",
4803 addr, VTY_NEWLINE);
4804 }
4805 }
4806
4807 /* Default information */
4808 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4809 && ! peer->af_group[afi][safi])
4810 {
4811 vty_out (vty, " neighbor %s default-originate", addr);
4812 if (peer->default_rmap[afi][safi].name)
4813 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4814 vty_out (vty, "%s", VTY_NEWLINE);
4815 }
4816
4817 /* Soft reconfiguration inbound. */
4818 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4819 if (! peer->af_group[afi][safi] ||
4820 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4821 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4822 VTY_NEWLINE);
4823
4824 /* maximum-prefix. */
4825 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4826 if (! peer->af_group[afi][safi]
4827 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004828 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004829 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4830 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004831 {
hasso0a486e52005-02-01 20:57:17 +00004832 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4833 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4834 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4835 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4836 vty_out (vty, " warning-only");
4837 if (peer->pmax_restart[afi][safi])
4838 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4839 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004840 }
paul718e3742002-12-13 20:15:29 +00004841
4842 /* Route server client. */
4843 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4844 && ! peer->af_group[afi][safi])
4845 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4846
Dylan Hall8b1eb592011-10-27 15:28:17 +04004847 /* Nexthop-local unchanged. */
4848 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
4849 && ! peer->af_group[afi][safi])
4850 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
4851
paul718e3742002-12-13 20:15:29 +00004852 /* Allow AS in. */
4853 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4854 if (! peer_group_active (peer)
4855 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4856 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4857 {
4858 if (peer->allowas_in[afi][safi] == 3)
4859 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4860 else
4861 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4862 peer->allowas_in[afi][safi], VTY_NEWLINE);
4863 }
4864
4865 /* Filter. */
4866 bgp_config_write_filter (vty, peer, afi, safi);
4867
4868 /* atribute-unchanged. */
4869 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4870 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4871 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4872 && ! peer->af_group[afi][safi])
4873 {
4874 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4875 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4876 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4877 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4878 else
4879 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4880 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4881 " as-path" : "",
4882 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4883 " next-hop" : "",
4884 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4885 " med" : "", VTY_NEWLINE);
4886 }
4887}
4888
4889/* Display "address-family" configuration header. */
4890void
4891bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4892 int *write)
4893{
4894 if (*write)
4895 return;
4896
4897 if (afi == AFI_IP && safi == SAFI_UNICAST)
4898 return;
4899
4900 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4901
4902 if (afi == AFI_IP)
4903 {
4904 if (safi == SAFI_MULTICAST)
4905 vty_out (vty, "ipv4 multicast");
4906 else if (safi == SAFI_MPLS_VPN)
4907 vty_out (vty, "vpnv4 unicast");
4908 }
4909 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004910 {
4911 vty_out (vty, "ipv6");
4912
4913 if (safi == SAFI_MULTICAST)
4914 vty_out (vty, " multicast");
4915 }
paul718e3742002-12-13 20:15:29 +00004916
4917 vty_out (vty, "%s", VTY_NEWLINE);
4918
4919 *write = 1;
4920}
4921
4922/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004923static int
paul718e3742002-12-13 20:15:29 +00004924bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4925 safi_t safi)
4926{
4927 int write = 0;
4928 struct peer *peer;
4929 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004930 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004931
4932 bgp_config_write_network (vty, bgp, afi, safi, &write);
4933
4934 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4935
paul1eb8ef22005-04-07 07:30:20 +00004936 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004937 {
4938 if (group->conf->afc[afi][safi])
4939 {
4940 bgp_config_write_family_header (vty, afi, safi, &write);
4941 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4942 }
4943 }
paul1eb8ef22005-04-07 07:30:20 +00004944 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004945 {
4946 if (peer->afc[afi][safi])
4947 {
4948 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4949 {
4950 bgp_config_write_family_header (vty, afi, safi, &write);
4951 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4952 }
4953 }
4954 }
4955 if (write)
4956 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4957
4958 return write;
4959}
4960
4961int
4962bgp_config_write (struct vty *vty)
4963{
4964 int write = 0;
4965 struct bgp *bgp;
4966 struct peer_group *group;
4967 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004968 struct listnode *node, *nnode;
4969 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004970
4971 /* BGP Multiple instance. */
4972 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4973 {
4974 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4975 write++;
4976 }
4977
4978 /* BGP Config type. */
4979 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4980 {
4981 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4982 write++;
4983 }
4984
4985 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004986 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004987 {
4988 if (write)
4989 vty_out (vty, "!%s", VTY_NEWLINE);
4990
4991 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004992 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004993
4994 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4995 {
4996 if (bgp->name)
4997 vty_out (vty, " view %s", bgp->name);
4998 }
4999 vty_out (vty, "%s", VTY_NEWLINE);
5000
5001 /* No Synchronization */
5002 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5003 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5004
5005 /* BGP fast-external-failover. */
5006 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5007 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5008
5009 /* BGP router ID. */
5010 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5011 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5012 VTY_NEWLINE);
5013
paul848973c2003-08-13 00:32:49 +00005014 /* BGP log-neighbor-changes. */
5015 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5016 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5017
paul718e3742002-12-13 20:15:29 +00005018 /* BGP configuration. */
5019 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5020 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5021
5022 /* BGP default ipv4-unicast. */
5023 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5024 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5025
5026 /* BGP default local-preference. */
5027 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5028 vty_out (vty, " bgp default local-preference %d%s",
5029 bgp->default_local_pref, VTY_NEWLINE);
5030
5031 /* BGP client-to-client reflection. */
5032 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5033 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5034
5035 /* BGP cluster ID. */
5036 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5037 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5038 VTY_NEWLINE);
5039
hassoe0701b72004-05-20 09:19:34 +00005040 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005041 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005042 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5043 VTY_NEWLINE);
5044
5045 /* Confederation peer */
5046 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005047 {
hassoe0701b72004-05-20 09:19:34 +00005048 int i;
paul718e3742002-12-13 20:15:29 +00005049
hassoe0701b72004-05-20 09:19:34 +00005050 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005051
hassoe0701b72004-05-20 09:19:34 +00005052 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005053 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005054
hassoe0701b72004-05-20 09:19:34 +00005055 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005056 }
5057
5058 /* BGP enforce-first-as. */
5059 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5060 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5061
5062 /* BGP deterministic-med. */
5063 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5064 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005065
5066 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005067 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5068 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5069 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005070 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5071 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5072
paul718e3742002-12-13 20:15:29 +00005073 /* BGP bestpath method. */
5074 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5075 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005076 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5077 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005078 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5079 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5080 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5081 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5082 {
5083 vty_out (vty, " bgp bestpath med");
5084 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5085 vty_out (vty, " confed");
5086 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5087 vty_out (vty, " missing-as-worst");
5088 vty_out (vty, "%s", VTY_NEWLINE);
5089 }
5090
5091 /* BGP network import check. */
5092 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5093 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5094
5095 /* BGP scan interval. */
5096 bgp_config_write_scan_time (vty);
5097
5098 /* BGP flag dampening. */
5099 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5100 BGP_CONFIG_DAMPENING))
5101 bgp_config_write_damp (vty);
5102
5103 /* BGP static route configuration. */
5104 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5105
5106 /* BGP redistribute configuration. */
5107 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5108
5109 /* BGP timers configuration. */
5110 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5111 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5112 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5113 bgp->default_holdtime, VTY_NEWLINE);
5114
5115 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005116 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005117 {
5118 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5119 }
5120
5121 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005122 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005123 {
5124 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5125 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5126 }
5127
5128 /* Distance configuration. */
5129 bgp_config_write_distance (vty, bgp);
5130
5131 /* No auto-summary */
5132 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5133 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5134
5135 /* IPv4 multicast configuration. */
5136 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5137
5138 /* IPv4 VPN configuration. */
5139 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5140
5141 /* IPv6 unicast configuration. */
5142 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5143
Paul Jakma37a217a2007-04-10 19:20:29 +00005144 /* IPv6 multicast configuration. */
5145 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5146
paul718e3742002-12-13 20:15:29 +00005147 write++;
5148 }
5149 return write;
5150}
5151
5152void
paul94f2b392005-06-28 12:44:16 +00005153bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005154{
5155 memset (&bgp_master, 0, sizeof (struct bgp_master));
5156
5157 bm = &bgp_master;
5158 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005159 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005160 bm->port = BGP_PORT_DEFAULT;
5161 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005162 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005163}
paul200df112005-06-01 11:17:05 +00005164
paul718e3742002-12-13 20:15:29 +00005165
5166void
paul94f2b392005-06-28 12:44:16 +00005167bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005168{
paul718e3742002-12-13 20:15:29 +00005169 /* BGP VTY commands installation. */
5170 bgp_vty_init ();
5171
paul718e3742002-12-13 20:15:29 +00005172 /* Init zebra. */
5173 bgp_zebra_init ();
5174
5175 /* BGP inits. */
5176 bgp_attr_init ();
5177 bgp_debug_init ();
5178 bgp_dump_init ();
5179 bgp_route_init ();
5180 bgp_route_map_init ();
5181 bgp_scan_init ();
5182 bgp_mplsvpn_init ();
5183
5184 /* Access list initialize. */
5185 access_list_init ();
5186 access_list_add_hook (peer_distribute_update);
5187 access_list_delete_hook (peer_distribute_update);
5188
5189 /* Filter list initialize. */
5190 bgp_filter_init ();
5191 as_list_add_hook (peer_aslist_update);
5192 as_list_delete_hook (peer_aslist_update);
5193
5194 /* Prefix list initialize.*/
5195 prefix_list_init ();
5196 prefix_list_add_hook (peer_prefix_list_update);
5197 prefix_list_delete_hook (peer_prefix_list_update);
5198
5199 /* Community list initialize. */
5200 bgp_clist = community_list_init ();
5201
5202#ifdef HAVE_SNMP
5203 bgp_snmp_init ();
5204#endif /* HAVE_SNMP */
5205}
paul545acaf2004-04-20 15:13:15 +00005206
5207void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005208bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005209{
paul545acaf2004-04-20 15:13:15 +00005210 struct bgp *bgp;
5211 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005212 struct listnode *node, *nnode;
5213 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005214
paul1eb8ef22005-04-07 07:30:20 +00005215 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5216 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005217 if (peer->status == Established)
5218 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5219 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005220
paul545acaf2004-04-20 15:13:15 +00005221 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005222
paule210cf92005-06-15 19:15:35 +00005223 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005224 {
5225 work_queue_free (bm->process_main_queue);
5226 bm->process_main_queue = NULL;
5227 }
paule210cf92005-06-15 19:15:35 +00005228 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005229 {
5230 work_queue_free (bm->process_rsclient_queue);
5231 bm->process_rsclient_queue = NULL;
5232 }
paul545acaf2004-04-20 15:13:15 +00005233}