blob: 882fe37cad66b858e1155cbf1ebbf0b48bb435a5 [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++)
1150 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1151 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
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002047 /* Create BGP server socket, if first instance. */
2048 if (list_isempty(bm->bgp))
2049 {
2050 if (bgp_socket (bm->port, bm->address) < 0)
2051 return BGP_ERR_INVALID_VALUE;
2052 }
2053
paul718e3742002-12-13 20:15:29 +00002054 bgp = bgp_create (as, name);
2055 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002056 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002057 *bgp_val = bgp;
2058
2059 return 0;
2060}
2061
2062/* Delete BGP instance. */
2063int
2064bgp_delete (struct bgp *bgp)
2065{
2066 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002067 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002068 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002069 struct listnode *next;
2070 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002071 int i;
2072
2073 /* Delete static route. */
2074 bgp_static_delete (bgp);
2075
2076 /* Unset redistribution. */
2077 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2078 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2079 if (i != ZEBRA_ROUTE_BGP)
2080 bgp_redistribute_unset (bgp, afi, i);
2081
paul1eb8ef22005-04-07 07:30:20 +00002082 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2083 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002084
Chris Caputo228da422009-07-18 05:44:03 +00002085 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2086 peer_group_delete (group);
2087
2088 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002089
2090 if (bgp->peer_self) {
2091 peer_delete(bgp->peer_self);
2092 bgp->peer_self = NULL;
2093 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002094
2095 /* Remove visibility via the master list - there may however still be
2096 * routes to be processed still referencing the struct bgp.
2097 */
2098 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002099 if (list_isempty(bm->bgp))
2100 bgp_close ();
2101
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002102 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002103
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002104 return 0;
2105}
2106
2107static void bgp_free (struct bgp *);
2108
2109void
2110bgp_lock (struct bgp *bgp)
2111{
2112 ++bgp->lock;
2113}
2114
2115void
2116bgp_unlock(struct bgp *bgp)
2117{
Chris Caputo228da422009-07-18 05:44:03 +00002118 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002119 if (--bgp->lock == 0)
2120 bgp_free (bgp);
2121}
2122
2123static void
2124bgp_free (struct bgp *bgp)
2125{
2126 afi_t afi;
2127 safi_t safi;
2128
2129 list_delete (bgp->group);
2130 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002131 list_delete (bgp->rsclient);
2132
paul718e3742002-12-13 20:15:29 +00002133 if (bgp->name)
2134 free (bgp->name);
2135
2136 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2137 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2138 {
2139 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002140 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002141 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002142 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002143 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002144 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002145 }
2146 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002147}
2148
2149struct peer *
2150peer_lookup (struct bgp *bgp, union sockunion *su)
2151{
2152 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002153 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002154
Steve Hillfc4dc592009-07-28 17:54:35 +01002155 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002156 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002157 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2158 if (sockunion_same (&peer->su, su)
2159 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2160 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002161 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002162 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002163 {
2164 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002165
Paul Jakma2158ad22009-07-28 18:10:55 +01002166 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2167 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2168 if (sockunion_same (&peer->su, su)
2169 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2170 return peer;
paul718e3742002-12-13 20:15:29 +00002171 }
2172 return NULL;
2173}
2174
2175struct peer *
2176peer_lookup_with_open (union sockunion *su, as_t remote_as,
2177 struct in_addr *remote_id, int *as)
2178{
2179 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002180 struct listnode *node;
2181 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002182 struct bgp *bgp;
2183
Steve Hillfc4dc592009-07-28 17:54:35 +01002184 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002185 return NULL;
2186
Paul Jakma9d878772009-08-05 16:25:16 +01002187 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002188 {
Paul Jakma9d878772009-08-05 16:25:16 +01002189 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2190 {
2191 if (sockunion_same (&peer->su, su)
2192 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2193 {
2194 if (peer->as == remote_as
2195 && peer->remote_id.s_addr == remote_id->s_addr)
2196 return peer;
2197 if (peer->as == remote_as)
2198 *as = 1;
2199 }
2200 }
2201
2202 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2203 {
2204 if (sockunion_same (&peer->su, su)
2205 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2206 {
2207 if (peer->as == remote_as
2208 && peer->remote_id.s_addr == 0)
2209 return peer;
2210 if (peer->as == remote_as)
2211 *as = 1;
2212 }
2213 }
paul718e3742002-12-13 20:15:29 +00002214 }
2215 return NULL;
2216}
2217
2218/* If peer is configured at least one address family return 1. */
2219int
2220peer_active (struct peer *peer)
2221{
2222 if (peer->afc[AFI_IP][SAFI_UNICAST]
2223 || peer->afc[AFI_IP][SAFI_MULTICAST]
2224 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2225 || peer->afc[AFI_IP6][SAFI_UNICAST]
2226 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2227 return 1;
2228 return 0;
2229}
2230
2231/* If peer is negotiated at least one address family return 1. */
2232int
2233peer_active_nego (struct peer *peer)
2234{
2235 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2236 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2237 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2238 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2239 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2240 return 1;
2241 return 0;
2242}
2243
2244/* peer_flag_change_type. */
2245enum peer_change_type
2246{
2247 peer_change_none,
2248 peer_change_reset,
2249 peer_change_reset_in,
2250 peer_change_reset_out,
2251};
2252
paul94f2b392005-06-28 12:44:16 +00002253static void
paul718e3742002-12-13 20:15:29 +00002254peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2255 enum peer_change_type type)
2256{
2257 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2258 return;
2259
2260 if (type == peer_change_reset)
2261 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2262 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2263 else if (type == peer_change_reset_in)
2264 {
2265 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2266 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2267 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2268 else
2269 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2270 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2271 }
2272 else if (type == peer_change_reset_out)
2273 bgp_announce_route (peer, afi, safi);
2274}
2275
2276struct peer_flag_action
2277{
2278 /* Peer's flag. */
2279 u_int32_t flag;
2280
2281 /* This flag can be set for peer-group member. */
2282 u_char not_for_member;
2283
2284 /* Action when the flag is changed. */
2285 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002286
2287 /* Peer down cause */
2288 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002289};
2290
Stephen Hemminger03621952009-07-21 16:27:20 -07002291static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002292 {
2293 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2294 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2295 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2296 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2297 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002298 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002299 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002300 { 0, 0, 0 }
2301 };
2302
Stephen Hemminger03621952009-07-21 16:27:20 -07002303static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002304 {
2305 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2306 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2307 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2308 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2309 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2310 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2311 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2312 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2313 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2314 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2315 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2316 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2317 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002318 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002319 { 0, 0, 0 }
2320 };
2321
2322/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002323static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002324peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002325 struct peer_flag_action *action, u_int32_t flag)
2326{
2327 int i;
2328 int found = 0;
2329 int reset_in = 0;
2330 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002331 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002332
2333 /* Check peer's frag action. */
2334 for (i = 0; i < size; i++)
2335 {
2336 match = &action_list[i];
2337
2338 if (match->flag == 0)
2339 break;
2340
2341 if (match->flag & flag)
2342 {
2343 found = 1;
2344
2345 if (match->type == peer_change_reset_in)
2346 reset_in = 1;
2347 if (match->type == peer_change_reset_out)
2348 reset_out = 1;
2349 if (match->type == peer_change_reset)
2350 {
2351 reset_in = 1;
2352 reset_out = 1;
2353 }
2354 if (match->not_for_member)
2355 action->not_for_member = 1;
2356 }
2357 }
2358
2359 /* Set peer clear type. */
2360 if (reset_in && reset_out)
2361 action->type = peer_change_reset;
2362 else if (reset_in)
2363 action->type = peer_change_reset_in;
2364 else if (reset_out)
2365 action->type = peer_change_reset_out;
2366 else
2367 action->type = peer_change_none;
2368
2369 return found;
2370}
2371
paul94f2b392005-06-28 12:44:16 +00002372static void
paul718e3742002-12-13 20:15:29 +00002373peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2374{
2375 if (flag == PEER_FLAG_SHUTDOWN)
2376 {
2377 if (CHECK_FLAG (peer->flags, flag))
2378 {
hasso93406d82005-02-02 14:40:33 +00002379 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2380 peer_nsf_stop (peer);
2381
hasso0a486e52005-02-01 20:57:17 +00002382 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2383 if (peer->t_pmax_restart)
2384 {
2385 BGP_TIMER_OFF (peer->t_pmax_restart);
2386 if (BGP_DEBUG (events, EVENTS))
2387 zlog_debug ("%s Maximum-prefix restart timer canceled",
2388 peer->host);
2389 }
2390
hasso93406d82005-02-02 14:40:33 +00002391 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2392 peer_nsf_stop (peer);
2393
paul718e3742002-12-13 20:15:29 +00002394 if (peer->status == Established)
2395 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2396 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2397 else
2398 BGP_EVENT_ADD (peer, BGP_Stop);
2399 }
2400 else
2401 {
2402 peer->v_start = BGP_INIT_START_TIMER;
2403 BGP_EVENT_ADD (peer, BGP_Stop);
2404 }
2405 }
2406 else if (peer->status == Established)
2407 {
hassoc9502432005-02-01 22:01:48 +00002408 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2409 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2410 else if (flag == PEER_FLAG_PASSIVE)
2411 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002412 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002413 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002414
hassoc9502432005-02-01 22:01:48 +00002415 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2416 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002417 }
2418 else
2419 BGP_EVENT_ADD (peer, BGP_Stop);
2420}
2421
2422/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002423static int
paul718e3742002-12-13 20:15:29 +00002424peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2425{
2426 int found;
2427 int size;
2428 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002429 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002430 struct peer_flag_action action;
2431
2432 memset (&action, 0, sizeof (struct peer_flag_action));
2433 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2434
2435 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2436
2437 /* No flag action is found. */
2438 if (! found)
2439 return BGP_ERR_INVALID_FLAG;
2440
2441 /* Not for peer-group member. */
2442 if (action.not_for_member && peer_group_active (peer))
2443 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2444
2445 /* When unset the peer-group member's flag we have to check
2446 peer-group configuration. */
2447 if (! set && peer_group_active (peer))
2448 if (CHECK_FLAG (peer->group->conf->flags, flag))
2449 {
2450 if (flag == PEER_FLAG_SHUTDOWN)
2451 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2452 else
2453 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2454 }
2455
2456 /* Flag conflict check. */
2457 if (set
2458 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2459 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2460 return BGP_ERR_PEER_FLAG_CONFLICT;
2461
2462 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2463 {
2464 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2465 return 0;
2466 if (! set && ! CHECK_FLAG (peer->flags, flag))
2467 return 0;
2468 }
2469
2470 if (set)
2471 SET_FLAG (peer->flags, flag);
2472 else
2473 UNSET_FLAG (peer->flags, flag);
2474
2475 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2476 {
2477 if (action.type == peer_change_reset)
2478 peer_flag_modify_action (peer, flag);
2479
2480 return 0;
2481 }
2482
2483 /* peer-group member updates. */
2484 group = peer->group;
2485
paul1eb8ef22005-04-07 07:30:20 +00002486 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002487 {
2488 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2489 continue;
2490
2491 if (! set && ! CHECK_FLAG (peer->flags, flag))
2492 continue;
2493
2494 if (set)
2495 SET_FLAG (peer->flags, flag);
2496 else
2497 UNSET_FLAG (peer->flags, flag);
2498
2499 if (action.type == peer_change_reset)
2500 peer_flag_modify_action (peer, flag);
2501 }
2502 return 0;
2503}
2504
2505int
2506peer_flag_set (struct peer *peer, u_int32_t flag)
2507{
2508 return peer_flag_modify (peer, flag, 1);
2509}
2510
2511int
2512peer_flag_unset (struct peer *peer, u_int32_t flag)
2513{
2514 return peer_flag_modify (peer, flag, 0);
2515}
2516
paul94f2b392005-06-28 12:44:16 +00002517static int
paul718e3742002-12-13 20:15:29 +00002518peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2519{
2520 if (peer->af_group[afi][safi])
2521 return 1;
2522 return 0;
2523}
2524
paul94f2b392005-06-28 12:44:16 +00002525static int
paul718e3742002-12-13 20:15:29 +00002526peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2527 int set)
2528{
2529 int found;
2530 int size;
paul1eb8ef22005-04-07 07:30:20 +00002531 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002532 struct peer_group *group;
2533 struct peer_flag_action action;
2534
2535 memset (&action, 0, sizeof (struct peer_flag_action));
2536 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2537
2538 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2539
2540 /* No flag action is found. */
2541 if (! found)
2542 return BGP_ERR_INVALID_FLAG;
2543
2544 /* Adress family must be activated. */
2545 if (! peer->afc[afi][safi])
2546 return BGP_ERR_PEER_INACTIVE;
2547
2548 /* Not for peer-group member. */
2549 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2550 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2551
2552 /* Spcecial check for reflector client. */
2553 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2554 && peer_sort (peer) != BGP_PEER_IBGP)
2555 return BGP_ERR_NOT_INTERNAL_PEER;
2556
2557 /* Spcecial check for remove-private-AS. */
2558 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2559 && peer_sort (peer) == BGP_PEER_IBGP)
2560 return BGP_ERR_REMOVE_PRIVATE_AS;
2561
2562 /* When unset the peer-group member's flag we have to check
2563 peer-group configuration. */
2564 if (! set && peer->af_group[afi][safi])
2565 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2566 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2567
2568 /* When current flag configuration is same as requested one. */
2569 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2570 {
2571 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2572 return 0;
2573 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2574 return 0;
2575 }
2576
2577 if (set)
2578 SET_FLAG (peer->af_flags[afi][safi], flag);
2579 else
2580 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2581
2582 /* Execute action when peer is established. */
2583 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2584 && peer->status == Established)
2585 {
2586 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2587 bgp_clear_adj_in (peer, afi, safi);
2588 else
hassoe0701b72004-05-20 09:19:34 +00002589 {
2590 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2591 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2592 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2593 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2594 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2595 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2596 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2597 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2598
2599 peer_change_action (peer, afi, safi, action.type);
2600 }
2601
paul718e3742002-12-13 20:15:29 +00002602 }
2603
2604 /* Peer group member updates. */
2605 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2606 {
2607 group = peer->group;
2608
paul1eb8ef22005-04-07 07:30:20 +00002609 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002610 {
2611 if (! peer->af_group[afi][safi])
2612 continue;
2613
2614 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2615 continue;
2616
2617 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2618 continue;
2619
2620 if (set)
2621 SET_FLAG (peer->af_flags[afi][safi], flag);
2622 else
2623 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2624
2625 if (peer->status == Established)
2626 {
2627 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2628 bgp_clear_adj_in (peer, afi, safi);
2629 else
hassoe0701b72004-05-20 09:19:34 +00002630 {
2631 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2632 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2633 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2634 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2635 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2636 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2637 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2638 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2639
2640 peer_change_action (peer, afi, safi, action.type);
2641 }
paul718e3742002-12-13 20:15:29 +00002642 }
2643 }
2644 }
2645 return 0;
2646}
2647
2648int
2649peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2650{
2651 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2652}
2653
2654int
2655peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2656{
2657 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2658}
2659
2660/* EBGP multihop configuration. */
2661int
2662peer_ebgp_multihop_set (struct peer *peer, int ttl)
2663{
2664 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002665 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002666
2667 if (peer_sort (peer) == BGP_PEER_IBGP)
2668 return 0;
2669
2670 peer->ttl = ttl;
2671
2672 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2673 {
pauleb821182004-05-01 08:44:08 +00002674 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2675 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002676 }
2677 else
2678 {
2679 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002681 {
2682 if (peer_sort (peer) == BGP_PEER_IBGP)
2683 continue;
paul718e3742002-12-13 20:15:29 +00002684
pauleb821182004-05-01 08:44:08 +00002685 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002686
pauleb821182004-05-01 08:44:08 +00002687 if (peer->fd >= 0)
2688 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2689 }
paul718e3742002-12-13 20:15:29 +00002690 }
2691 return 0;
2692}
2693
2694int
2695peer_ebgp_multihop_unset (struct peer *peer)
2696{
2697 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002698 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002699
2700 if (peer_sort (peer) == BGP_PEER_IBGP)
2701 return 0;
2702
2703 if (peer_group_active (peer))
2704 peer->ttl = peer->group->conf->ttl;
2705 else
2706 peer->ttl = 1;
2707
2708 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2709 {
pauleb821182004-05-01 08:44:08 +00002710 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2711 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002712 }
2713 else
2714 {
2715 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002716 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002717 {
2718 if (peer_sort (peer) == BGP_PEER_IBGP)
2719 continue;
paul718e3742002-12-13 20:15:29 +00002720
pauleb821182004-05-01 08:44:08 +00002721 peer->ttl = 1;
2722
2723 if (peer->fd >= 0)
2724 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2725 }
paul718e3742002-12-13 20:15:29 +00002726 }
2727 return 0;
2728}
2729
2730/* Neighbor description. */
2731int
2732peer_description_set (struct peer *peer, char *desc)
2733{
2734 if (peer->desc)
2735 XFREE (MTYPE_PEER_DESC, peer->desc);
2736
2737 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2738
2739 return 0;
2740}
2741
2742int
2743peer_description_unset (struct peer *peer)
2744{
2745 if (peer->desc)
2746 XFREE (MTYPE_PEER_DESC, peer->desc);
2747
2748 peer->desc = NULL;
2749
2750 return 0;
2751}
2752
2753/* Neighbor update-source. */
2754int
paulfd79ac92004-10-13 05:06:08 +00002755peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002756{
2757 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002758 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002759
2760 if (peer->update_if)
2761 {
2762 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2763 && strcmp (peer->update_if, ifname) == 0)
2764 return 0;
2765
2766 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2767 peer->update_if = NULL;
2768 }
2769
2770 if (peer->update_source)
2771 {
2772 sockunion_free (peer->update_source);
2773 peer->update_source = NULL;
2774 }
2775
2776 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2777
2778 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2779 {
2780 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002781 {
2782 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2783 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2784 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2785 }
paul718e3742002-12-13 20:15:29 +00002786 else
2787 BGP_EVENT_ADD (peer, BGP_Stop);
2788 return 0;
2789 }
2790
2791 /* peer-group member updates. */
2792 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002793 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002794 {
2795 if (peer->update_if)
2796 {
2797 if (strcmp (peer->update_if, ifname) == 0)
2798 continue;
2799
2800 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2801 peer->update_if = NULL;
2802 }
2803
2804 if (peer->update_source)
2805 {
2806 sockunion_free (peer->update_source);
2807 peer->update_source = NULL;
2808 }
2809
2810 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2811
2812 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002813 {
2814 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2815 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2816 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2817 }
paul718e3742002-12-13 20:15:29 +00002818 else
2819 BGP_EVENT_ADD (peer, BGP_Stop);
2820 }
2821 return 0;
2822}
2823
2824int
2825peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2826{
2827 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002828 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002829
2830 if (peer->update_source)
2831 {
2832 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2833 && sockunion_cmp (peer->update_source, su) == 0)
2834 return 0;
2835 sockunion_free (peer->update_source);
2836 peer->update_source = NULL;
2837 }
2838
2839 if (peer->update_if)
2840 {
2841 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2842 peer->update_if = NULL;
2843 }
2844
2845 peer->update_source = sockunion_dup (su);
2846
2847 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2848 {
2849 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002850 {
2851 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2852 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2853 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2854 }
paul718e3742002-12-13 20:15:29 +00002855 else
2856 BGP_EVENT_ADD (peer, BGP_Stop);
2857 return 0;
2858 }
2859
2860 /* peer-group member updates. */
2861 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002862 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002863 {
2864 if (peer->update_source)
2865 {
2866 if (sockunion_cmp (peer->update_source, su) == 0)
2867 continue;
2868 sockunion_free (peer->update_source);
2869 peer->update_source = NULL;
2870 }
2871
2872 if (peer->update_if)
2873 {
2874 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2875 peer->update_if = NULL;
2876 }
2877
2878 peer->update_source = sockunion_dup (su);
2879
2880 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002881 {
2882 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2883 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2884 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2885 }
paul718e3742002-12-13 20:15:29 +00002886 else
2887 BGP_EVENT_ADD (peer, BGP_Stop);
2888 }
2889 return 0;
2890}
2891
2892int
2893peer_update_source_unset (struct peer *peer)
2894{
2895 union sockunion *su;
2896 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002897 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002898
2899 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2900 && ! peer->update_source
2901 && ! peer->update_if)
2902 return 0;
2903
2904 if (peer->update_source)
2905 {
2906 sockunion_free (peer->update_source);
2907 peer->update_source = NULL;
2908 }
2909 if (peer->update_if)
2910 {
2911 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2912 peer->update_if = NULL;
2913 }
2914
2915 if (peer_group_active (peer))
2916 {
2917 group = peer->group;
2918
2919 if (group->conf->update_source)
2920 {
2921 su = sockunion_dup (group->conf->update_source);
2922 peer->update_source = su;
2923 }
2924 else if (group->conf->update_if)
2925 peer->update_if =
2926 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2927 }
2928
2929 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2930 {
2931 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002932 {
2933 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2934 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2935 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2936 }
paul718e3742002-12-13 20:15:29 +00002937 else
2938 BGP_EVENT_ADD (peer, BGP_Stop);
2939 return 0;
2940 }
2941
2942 /* peer-group member updates. */
2943 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002944 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002945 {
2946 if (! peer->update_source && ! peer->update_if)
2947 continue;
2948
2949 if (peer->update_source)
2950 {
2951 sockunion_free (peer->update_source);
2952 peer->update_source = NULL;
2953 }
2954
2955 if (peer->update_if)
2956 {
2957 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2958 peer->update_if = NULL;
2959 }
2960
2961 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002962 {
2963 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2964 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2965 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2966 }
paul718e3742002-12-13 20:15:29 +00002967 else
2968 BGP_EVENT_ADD (peer, BGP_Stop);
2969 }
2970 return 0;
2971}
2972
2973int
2974peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002975 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002976{
2977 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002978 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002979
2980 /* Adress family must be activated. */
2981 if (! peer->afc[afi][safi])
2982 return BGP_ERR_PEER_INACTIVE;
2983
2984 /* Default originate can't be used for peer group memeber. */
2985 if (peer_is_group_member (peer, afi, safi))
2986 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2987
2988 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2989 || (rmap && ! peer->default_rmap[afi][safi].name)
2990 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2991 {
2992 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2993
2994 if (rmap)
2995 {
2996 if (peer->default_rmap[afi][safi].name)
2997 free (peer->default_rmap[afi][safi].name);
2998 peer->default_rmap[afi][safi].name = strdup (rmap);
2999 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3000 }
3001 }
3002
3003 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3004 {
3005 if (peer->status == Established && peer->afc_nego[afi][safi])
3006 bgp_default_originate (peer, afi, safi, 0);
3007 return 0;
3008 }
3009
3010 /* peer-group member updates. */
3011 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003012 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003013 {
3014 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3015
3016 if (rmap)
3017 {
3018 if (peer->default_rmap[afi][safi].name)
3019 free (peer->default_rmap[afi][safi].name);
3020 peer->default_rmap[afi][safi].name = strdup (rmap);
3021 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3022 }
3023
3024 if (peer->status == Established && peer->afc_nego[afi][safi])
3025 bgp_default_originate (peer, afi, safi, 0);
3026 }
3027 return 0;
3028}
3029
3030int
3031peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3032{
3033 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003034 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003035
3036 /* Adress family must be activated. */
3037 if (! peer->afc[afi][safi])
3038 return BGP_ERR_PEER_INACTIVE;
3039
3040 /* Default originate can't be used for peer group memeber. */
3041 if (peer_is_group_member (peer, afi, safi))
3042 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3043
3044 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3045 {
3046 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3047
3048 if (peer->default_rmap[afi][safi].name)
3049 free (peer->default_rmap[afi][safi].name);
3050 peer->default_rmap[afi][safi].name = NULL;
3051 peer->default_rmap[afi][safi].map = NULL;
3052 }
3053
3054 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3055 {
3056 if (peer->status == Established && peer->afc_nego[afi][safi])
3057 bgp_default_originate (peer, afi, safi, 1);
3058 return 0;
3059 }
3060
3061 /* peer-group member updates. */
3062 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003063 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003064 {
3065 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3066
3067 if (peer->default_rmap[afi][safi].name)
3068 free (peer->default_rmap[afi][safi].name);
3069 peer->default_rmap[afi][safi].name = NULL;
3070 peer->default_rmap[afi][safi].map = NULL;
3071
3072 if (peer->status == Established && peer->afc_nego[afi][safi])
3073 bgp_default_originate (peer, afi, safi, 1);
3074 }
3075 return 0;
3076}
3077
3078int
3079peer_port_set (struct peer *peer, u_int16_t port)
3080{
3081 peer->port = port;
3082 return 0;
3083}
3084
3085int
3086peer_port_unset (struct peer *peer)
3087{
3088 peer->port = BGP_PORT_DEFAULT;
3089 return 0;
3090}
3091
3092/* neighbor weight. */
3093int
3094peer_weight_set (struct peer *peer, u_int16_t weight)
3095{
3096 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003097 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003098
3099 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3100 peer->weight = weight;
3101
3102 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3103 return 0;
3104
3105 /* peer-group member updates. */
3106 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003107 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003108 {
3109 peer->weight = group->conf->weight;
3110 }
3111 return 0;
3112}
3113
3114int
3115peer_weight_unset (struct peer *peer)
3116{
3117 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003118 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003119
3120 /* Set default weight. */
3121 if (peer_group_active (peer))
3122 peer->weight = peer->group->conf->weight;
3123 else
3124 peer->weight = 0;
3125
3126 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3127
3128 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3129 return 0;
3130
3131 /* peer-group member updates. */
3132 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003133 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003134 {
3135 peer->weight = 0;
3136 }
3137 return 0;
3138}
3139
3140int
3141peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3142{
3143 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003144 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003145
3146 /* Not for peer group memeber. */
3147 if (peer_group_active (peer))
3148 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3149
3150 /* keepalive value check. */
3151 if (keepalive > 65535)
3152 return BGP_ERR_INVALID_VALUE;
3153
3154 /* Holdtime value check. */
3155 if (holdtime > 65535)
3156 return BGP_ERR_INVALID_VALUE;
3157
3158 /* Holdtime value must be either 0 or greater than 3. */
3159 if (holdtime < 3 && holdtime != 0)
3160 return BGP_ERR_INVALID_VALUE;
3161
3162 /* Set value to the configuration. */
3163 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3164 peer->holdtime = holdtime;
3165 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3166
3167 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3168 return 0;
3169
3170 /* peer-group member updates. */
3171 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003172 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003173 {
3174 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3175 peer->holdtime = group->conf->holdtime;
3176 peer->keepalive = group->conf->keepalive;
3177 }
3178 return 0;
3179}
3180
3181int
3182peer_timers_unset (struct peer *peer)
3183{
3184 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003185 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003186
3187 if (peer_group_active (peer))
3188 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3189
3190 /* Clear configuration. */
3191 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3192 peer->keepalive = 0;
3193 peer->holdtime = 0;
3194
3195 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3196 return 0;
3197
3198 /* peer-group member updates. */
3199 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003200 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003201 {
3202 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3203 peer->holdtime = 0;
3204 peer->keepalive = 0;
3205 }
3206
3207 return 0;
3208}
3209
3210int
3211peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3212{
3213 if (peer_group_active (peer))
3214 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3215
3216 if (connect > 65535)
3217 return BGP_ERR_INVALID_VALUE;
3218
3219 /* Set value to the configuration. */
3220 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3221 peer->connect = connect;
3222
3223 /* Set value to timer setting. */
3224 peer->v_connect = connect;
3225
3226 return 0;
3227}
3228
3229int
3230peer_timers_connect_unset (struct peer *peer)
3231{
3232 if (peer_group_active (peer))
3233 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3234
3235 /* Clear configuration. */
3236 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3237 peer->connect = 0;
3238
3239 /* Set timer setting to default value. */
3240 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3241
3242 return 0;
3243}
3244
3245int
3246peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3247{
3248 if (peer_group_active (peer))
3249 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3250
3251 if (routeadv > 600)
3252 return BGP_ERR_INVALID_VALUE;
3253
3254 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3255 peer->routeadv = routeadv;
3256 peer->v_routeadv = routeadv;
3257
3258 return 0;
3259}
3260
3261int
3262peer_advertise_interval_unset (struct peer *peer)
3263{
3264 if (peer_group_active (peer))
3265 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3266
3267 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3268 peer->routeadv = 0;
3269
3270 if (peer_sort (peer) == BGP_PEER_IBGP)
3271 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3272 else
3273 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3274
3275 return 0;
3276}
3277
paul718e3742002-12-13 20:15:29 +00003278/* neighbor interface */
3279int
paulfd79ac92004-10-13 05:06:08 +00003280peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003281{
3282 if (peer->ifname)
3283 free (peer->ifname);
3284 peer->ifname = strdup (str);
3285
3286 return 0;
3287}
3288
3289int
3290peer_interface_unset (struct peer *peer)
3291{
3292 if (peer->ifname)
3293 free (peer->ifname);
3294 peer->ifname = NULL;
3295
3296 return 0;
3297}
3298
3299/* Allow-as in. */
3300int
3301peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3302{
3303 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003304 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003305
3306 if (allow_num < 1 || allow_num > 10)
3307 return BGP_ERR_INVALID_VALUE;
3308
3309 if (peer->allowas_in[afi][safi] != allow_num)
3310 {
3311 peer->allowas_in[afi][safi] = allow_num;
3312 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3313 peer_change_action (peer, afi, safi, peer_change_reset_in);
3314 }
3315
3316 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3317 return 0;
3318
3319 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003320 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003321 {
3322 if (peer->allowas_in[afi][safi] != allow_num)
3323 {
3324 peer->allowas_in[afi][safi] = allow_num;
3325 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3326 peer_change_action (peer, afi, safi, peer_change_reset_in);
3327 }
3328
3329 }
3330 return 0;
3331}
3332
3333int
3334peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3335{
3336 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003337 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003338
3339 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3340 {
3341 peer->allowas_in[afi][safi] = 0;
3342 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3343 }
3344
3345 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3346 return 0;
3347
3348 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003349 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003350 {
3351 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3352 {
3353 peer->allowas_in[afi][safi] = 0;
3354 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3355 }
3356 }
3357 return 0;
3358}
3359
3360int
3361peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3362{
3363 struct bgp *bgp = peer->bgp;
3364 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003365 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003366
3367 if (peer_sort (peer) != BGP_PEER_EBGP
3368 && peer_sort (peer) != BGP_PEER_INTERNAL)
3369 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3370
3371 if (bgp->as == as)
3372 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3373
3374 if (peer_group_active (peer))
3375 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3376
3377 if (peer->change_local_as == as &&
3378 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3379 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3380 return 0;
3381
3382 peer->change_local_as = as;
3383 if (no_prepend)
3384 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3385 else
3386 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3387
3388 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3389 {
3390 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003391 {
3392 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3393 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3394 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3395 }
paul718e3742002-12-13 20:15:29 +00003396 else
3397 BGP_EVENT_ADD (peer, BGP_Stop);
3398
3399 return 0;
3400 }
3401
3402 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003403 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003404 {
3405 peer->change_local_as = as;
3406 if (no_prepend)
3407 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3408 else
3409 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3410
3411 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003412 {
3413 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3414 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3415 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3416 }
paul718e3742002-12-13 20:15:29 +00003417 else
3418 BGP_EVENT_ADD (peer, BGP_Stop);
3419 }
3420
3421 return 0;
3422}
3423
3424int
3425peer_local_as_unset (struct peer *peer)
3426{
3427 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003428 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003429
3430 if (peer_group_active (peer))
3431 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3432
3433 if (! peer->change_local_as)
3434 return 0;
3435
3436 peer->change_local_as = 0;
3437 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3438
3439 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3440 {
3441 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003442 {
3443 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3444 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3445 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3446 }
paul718e3742002-12-13 20:15:29 +00003447 else
3448 BGP_EVENT_ADD (peer, BGP_Stop);
3449
3450 return 0;
3451 }
3452
3453 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003454 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003455 {
3456 peer->change_local_as = 0;
3457 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3458
3459 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003460 {
3461 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3462 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3463 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3464 }
paul718e3742002-12-13 20:15:29 +00003465 else
3466 BGP_EVENT_ADD (peer, BGP_Stop);
3467 }
3468 return 0;
3469}
3470
Paul Jakma0df7c912008-07-21 21:02:49 +00003471/* Set password for authenticating with the peer. */
3472int
3473peer_password_set (struct peer *peer, const char *password)
3474{
3475 struct listnode *nn, *nnode;
3476 int len = password ? strlen(password) : 0;
3477 int ret = BGP_SUCCESS;
3478
3479 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3480 return BGP_ERR_INVALID_VALUE;
3481
3482 if (peer->password && strcmp (peer->password, password) == 0
3483 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3484 return 0;
3485
3486 if (peer->password)
3487 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3488
3489 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3490
3491 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3492 {
3493 if (peer->status == Established)
3494 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3495 else
3496 BGP_EVENT_ADD (peer, BGP_Stop);
3497
3498 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3499 }
3500
3501 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3502 {
3503 if (peer->password && strcmp (peer->password, password) == 0)
3504 continue;
3505
3506 if (peer->password)
3507 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3508
3509 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3510
3511 if (peer->status == Established)
3512 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3513 else
3514 BGP_EVENT_ADD (peer, BGP_Stop);
3515
3516 if (bgp_md5_set (peer) < 0)
3517 ret = BGP_ERR_TCPSIG_FAILED;
3518 }
3519
3520 return ret;
3521}
3522
3523int
3524peer_password_unset (struct peer *peer)
3525{
3526 struct listnode *nn, *nnode;
3527
3528 if (!peer->password
3529 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3530 return 0;
3531
3532 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3533 {
3534 if (peer_group_active (peer)
3535 && peer->group->conf->password
3536 && strcmp (peer->group->conf->password, peer->password) == 0)
3537 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3538
3539 if (peer->status == Established)
3540 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3541 else
3542 BGP_EVENT_ADD (peer, BGP_Stop);
3543
3544 if (peer->password)
3545 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3546
3547 peer->password = NULL;
3548
3549 bgp_md5_set (peer);
3550
3551 return 0;
3552 }
3553
3554 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3555 peer->password = NULL;
3556
3557 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3558 {
3559 if (!peer->password)
3560 continue;
3561
3562 if (peer->status == Established)
3563 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3564 else
3565 BGP_EVENT_ADD (peer, BGP_Stop);
3566
3567 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3568 peer->password = NULL;
3569
3570 bgp_md5_set (peer);
3571 }
3572
3573 return 0;
3574}
3575
paul718e3742002-12-13 20:15:29 +00003576/* Set distribute list to the peer. */
3577int
3578peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003579 const char *name)
paul718e3742002-12-13 20:15:29 +00003580{
3581 struct bgp_filter *filter;
3582 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003583 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003584
3585 if (! peer->afc[afi][safi])
3586 return BGP_ERR_PEER_INACTIVE;
3587
3588 if (direct != FILTER_IN && direct != FILTER_OUT)
3589 return BGP_ERR_INVALID_VALUE;
3590
3591 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3592 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3593
3594 filter = &peer->filter[afi][safi];
3595
3596 if (filter->plist[direct].name)
3597 return BGP_ERR_PEER_FILTER_CONFLICT;
3598
3599 if (filter->dlist[direct].name)
3600 free (filter->dlist[direct].name);
3601 filter->dlist[direct].name = strdup (name);
3602 filter->dlist[direct].alist = access_list_lookup (afi, name);
3603
3604 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3605 return 0;
3606
3607 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003608 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003609 {
3610 filter = &peer->filter[afi][safi];
3611
3612 if (! peer->af_group[afi][safi])
3613 continue;
3614
3615 if (filter->dlist[direct].name)
3616 free (filter->dlist[direct].name);
3617 filter->dlist[direct].name = strdup (name);
3618 filter->dlist[direct].alist = access_list_lookup (afi, name);
3619 }
3620
3621 return 0;
3622}
3623
3624int
3625peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3626{
3627 struct bgp_filter *filter;
3628 struct bgp_filter *gfilter;
3629 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003630 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003631
3632 if (! peer->afc[afi][safi])
3633 return BGP_ERR_PEER_INACTIVE;
3634
3635 if (direct != FILTER_IN && direct != FILTER_OUT)
3636 return BGP_ERR_INVALID_VALUE;
3637
3638 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3639 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3640
3641 filter = &peer->filter[afi][safi];
3642
3643 /* apply peer-group filter */
3644 if (peer->af_group[afi][safi])
3645 {
3646 gfilter = &peer->group->conf->filter[afi][safi];
3647
3648 if (gfilter->dlist[direct].name)
3649 {
3650 if (filter->dlist[direct].name)
3651 free (filter->dlist[direct].name);
3652 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3653 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3654 return 0;
3655 }
3656 }
3657
3658 if (filter->dlist[direct].name)
3659 free (filter->dlist[direct].name);
3660 filter->dlist[direct].name = NULL;
3661 filter->dlist[direct].alist = NULL;
3662
3663 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3664 return 0;
3665
3666 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003667 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003668 {
3669 filter = &peer->filter[afi][safi];
3670
3671 if (! peer->af_group[afi][safi])
3672 continue;
3673
3674 if (filter->dlist[direct].name)
3675 free (filter->dlist[direct].name);
3676 filter->dlist[direct].name = NULL;
3677 filter->dlist[direct].alist = NULL;
3678 }
3679
3680 return 0;
3681}
3682
3683/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003684static void
paul718e3742002-12-13 20:15:29 +00003685peer_distribute_update (struct access_list *access)
3686{
3687 afi_t afi;
3688 safi_t safi;
3689 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003690 struct listnode *mnode, *mnnode;
3691 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003692 struct bgp *bgp;
3693 struct peer *peer;
3694 struct peer_group *group;
3695 struct bgp_filter *filter;
3696
paul1eb8ef22005-04-07 07:30:20 +00003697 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003698 {
paul1eb8ef22005-04-07 07:30:20 +00003699 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003700 {
3701 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3702 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3703 {
3704 filter = &peer->filter[afi][safi];
3705
3706 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3707 {
3708 if (filter->dlist[direct].name)
3709 filter->dlist[direct].alist =
3710 access_list_lookup (afi, filter->dlist[direct].name);
3711 else
3712 filter->dlist[direct].alist = NULL;
3713 }
3714 }
3715 }
paul1eb8ef22005-04-07 07:30:20 +00003716 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003717 {
3718 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3719 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3720 {
3721 filter = &group->conf->filter[afi][safi];
3722
3723 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3724 {
3725 if (filter->dlist[direct].name)
3726 filter->dlist[direct].alist =
3727 access_list_lookup (afi, filter->dlist[direct].name);
3728 else
3729 filter->dlist[direct].alist = NULL;
3730 }
3731 }
3732 }
3733 }
3734}
3735
3736/* Set prefix list to the peer. */
3737int
3738peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003739 const char *name)
paul718e3742002-12-13 20:15:29 +00003740{
3741 struct bgp_filter *filter;
3742 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003743 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003744
3745 if (! peer->afc[afi][safi])
3746 return BGP_ERR_PEER_INACTIVE;
3747
3748 if (direct != FILTER_IN && direct != FILTER_OUT)
3749 return BGP_ERR_INVALID_VALUE;
3750
3751 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3752 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3753
3754 filter = &peer->filter[afi][safi];
3755
3756 if (filter->dlist[direct].name)
3757 return BGP_ERR_PEER_FILTER_CONFLICT;
3758
3759 if (filter->plist[direct].name)
3760 free (filter->plist[direct].name);
3761 filter->plist[direct].name = strdup (name);
3762 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3763
3764 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3765 return 0;
3766
3767 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003768 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003769 {
3770 filter = &peer->filter[afi][safi];
3771
3772 if (! peer->af_group[afi][safi])
3773 continue;
3774
3775 if (filter->plist[direct].name)
3776 free (filter->plist[direct].name);
3777 filter->plist[direct].name = strdup (name);
3778 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3779 }
3780 return 0;
3781}
3782
3783int
3784peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3785{
3786 struct bgp_filter *filter;
3787 struct bgp_filter *gfilter;
3788 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003789 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003790
3791 if (! peer->afc[afi][safi])
3792 return BGP_ERR_PEER_INACTIVE;
3793
3794 if (direct != FILTER_IN && direct != FILTER_OUT)
3795 return BGP_ERR_INVALID_VALUE;
3796
3797 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3798 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3799
3800 filter = &peer->filter[afi][safi];
3801
3802 /* apply peer-group filter */
3803 if (peer->af_group[afi][safi])
3804 {
3805 gfilter = &peer->group->conf->filter[afi][safi];
3806
3807 if (gfilter->plist[direct].name)
3808 {
3809 if (filter->plist[direct].name)
3810 free (filter->plist[direct].name);
3811 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3812 filter->plist[direct].plist = gfilter->plist[direct].plist;
3813 return 0;
3814 }
3815 }
3816
3817 if (filter->plist[direct].name)
3818 free (filter->plist[direct].name);
3819 filter->plist[direct].name = NULL;
3820 filter->plist[direct].plist = NULL;
3821
3822 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3823 return 0;
3824
3825 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003826 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003827 {
3828 filter = &peer->filter[afi][safi];
3829
3830 if (! peer->af_group[afi][safi])
3831 continue;
3832
3833 if (filter->plist[direct].name)
3834 free (filter->plist[direct].name);
3835 filter->plist[direct].name = NULL;
3836 filter->plist[direct].plist = NULL;
3837 }
3838
3839 return 0;
3840}
3841
3842/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003843static void
paul718e3742002-12-13 20:15:29 +00003844peer_prefix_list_update (struct prefix_list *plist)
3845{
paul1eb8ef22005-04-07 07:30:20 +00003846 struct listnode *mnode, *mnnode;
3847 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003848 struct bgp *bgp;
3849 struct peer *peer;
3850 struct peer_group *group;
3851 struct bgp_filter *filter;
3852 afi_t afi;
3853 safi_t safi;
3854 int direct;
3855
paul1eb8ef22005-04-07 07:30:20 +00003856 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003857 {
paul1eb8ef22005-04-07 07:30:20 +00003858 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003859 {
3860 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3861 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3862 {
3863 filter = &peer->filter[afi][safi];
3864
3865 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3866 {
3867 if (filter->plist[direct].name)
3868 filter->plist[direct].plist =
3869 prefix_list_lookup (afi, filter->plist[direct].name);
3870 else
3871 filter->plist[direct].plist = NULL;
3872 }
3873 }
3874 }
paul1eb8ef22005-04-07 07:30:20 +00003875 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003876 {
3877 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3878 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3879 {
3880 filter = &group->conf->filter[afi][safi];
3881
3882 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3883 {
3884 if (filter->plist[direct].name)
3885 filter->plist[direct].plist =
3886 prefix_list_lookup (afi, filter->plist[direct].name);
3887 else
3888 filter->plist[direct].plist = NULL;
3889 }
3890 }
3891 }
3892 }
3893}
3894
3895int
3896peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003897 const char *name)
paul718e3742002-12-13 20:15:29 +00003898{
3899 struct bgp_filter *filter;
3900 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003901 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003902
3903 if (! peer->afc[afi][safi])
3904 return BGP_ERR_PEER_INACTIVE;
3905
3906 if (direct != FILTER_IN && direct != FILTER_OUT)
3907 return BGP_ERR_INVALID_VALUE;
3908
3909 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3910 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3911
3912 filter = &peer->filter[afi][safi];
3913
3914 if (filter->aslist[direct].name)
3915 free (filter->aslist[direct].name);
3916 filter->aslist[direct].name = strdup (name);
3917 filter->aslist[direct].aslist = as_list_lookup (name);
3918
3919 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3920 return 0;
3921
3922 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003923 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003924 {
3925 filter = &peer->filter[afi][safi];
3926
3927 if (! peer->af_group[afi][safi])
3928 continue;
3929
3930 if (filter->aslist[direct].name)
3931 free (filter->aslist[direct].name);
3932 filter->aslist[direct].name = strdup (name);
3933 filter->aslist[direct].aslist = as_list_lookup (name);
3934 }
3935 return 0;
3936}
3937
3938int
3939peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3940{
3941 struct bgp_filter *filter;
3942 struct bgp_filter *gfilter;
3943 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003944 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003945
3946 if (! peer->afc[afi][safi])
3947 return BGP_ERR_PEER_INACTIVE;
3948
hassob5f29602005-05-25 21:00:28 +00003949 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003950 return BGP_ERR_INVALID_VALUE;
3951
hassob5f29602005-05-25 21:00:28 +00003952 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003953 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3954
3955 filter = &peer->filter[afi][safi];
3956
3957 /* apply peer-group filter */
3958 if (peer->af_group[afi][safi])
3959 {
3960 gfilter = &peer->group->conf->filter[afi][safi];
3961
3962 if (gfilter->aslist[direct].name)
3963 {
3964 if (filter->aslist[direct].name)
3965 free (filter->aslist[direct].name);
3966 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3967 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3968 return 0;
3969 }
3970 }
3971
3972 if (filter->aslist[direct].name)
3973 free (filter->aslist[direct].name);
3974 filter->aslist[direct].name = NULL;
3975 filter->aslist[direct].aslist = NULL;
3976
3977 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3978 return 0;
3979
3980 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003981 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003982 {
3983 filter = &peer->filter[afi][safi];
3984
3985 if (! peer->af_group[afi][safi])
3986 continue;
3987
3988 if (filter->aslist[direct].name)
3989 free (filter->aslist[direct].name);
3990 filter->aslist[direct].name = NULL;
3991 filter->aslist[direct].aslist = NULL;
3992 }
3993
3994 return 0;
3995}
3996
paul94f2b392005-06-28 12:44:16 +00003997static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08003998peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00003999{
4000 afi_t afi;
4001 safi_t safi;
4002 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004003 struct listnode *mnode, *mnnode;
4004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004005 struct bgp *bgp;
4006 struct peer *peer;
4007 struct peer_group *group;
4008 struct bgp_filter *filter;
4009
paul1eb8ef22005-04-07 07:30:20 +00004010 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004011 {
paul1eb8ef22005-04-07 07:30:20 +00004012 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004013 {
4014 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4015 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4016 {
4017 filter = &peer->filter[afi][safi];
4018
4019 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4020 {
4021 if (filter->aslist[direct].name)
4022 filter->aslist[direct].aslist =
4023 as_list_lookup (filter->aslist[direct].name);
4024 else
4025 filter->aslist[direct].aslist = NULL;
4026 }
4027 }
4028 }
paul1eb8ef22005-04-07 07:30:20 +00004029 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004030 {
4031 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4032 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4033 {
4034 filter = &group->conf->filter[afi][safi];
4035
4036 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4037 {
4038 if (filter->aslist[direct].name)
4039 filter->aslist[direct].aslist =
4040 as_list_lookup (filter->aslist[direct].name);
4041 else
4042 filter->aslist[direct].aslist = NULL;
4043 }
4044 }
4045 }
4046 }
4047}
4048
4049/* Set route-map to the peer. */
4050int
4051peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004052 const char *name)
paul718e3742002-12-13 20:15:29 +00004053{
4054 struct bgp_filter *filter;
4055 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004056 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004057
4058 if (! peer->afc[afi][safi])
4059 return BGP_ERR_PEER_INACTIVE;
4060
paulfee0f4c2004-09-13 05:12:46 +00004061 if (direct != RMAP_IN && direct != RMAP_OUT &&
4062 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004063 return BGP_ERR_INVALID_VALUE;
4064
paulfee0f4c2004-09-13 05:12:46 +00004065 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4066 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004067 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4068
4069 filter = &peer->filter[afi][safi];
4070
4071 if (filter->map[direct].name)
4072 free (filter->map[direct].name);
4073
4074 filter->map[direct].name = strdup (name);
4075 filter->map[direct].map = route_map_lookup_by_name (name);
4076
4077 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4078 return 0;
4079
4080 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004081 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004082 {
4083 filter = &peer->filter[afi][safi];
4084
4085 if (! peer->af_group[afi][safi])
4086 continue;
4087
4088 if (filter->map[direct].name)
4089 free (filter->map[direct].name);
4090 filter->map[direct].name = strdup (name);
4091 filter->map[direct].map = route_map_lookup_by_name (name);
4092 }
4093 return 0;
4094}
4095
4096/* Unset route-map from the peer. */
4097int
4098peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4099{
4100 struct bgp_filter *filter;
4101 struct bgp_filter *gfilter;
4102 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004104
4105 if (! peer->afc[afi][safi])
4106 return BGP_ERR_PEER_INACTIVE;
4107
hassob5f29602005-05-25 21:00:28 +00004108 if (direct != RMAP_IN && direct != RMAP_OUT &&
4109 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004110 return BGP_ERR_INVALID_VALUE;
4111
hassob5f29602005-05-25 21:00:28 +00004112 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4113 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004114 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4115
4116 filter = &peer->filter[afi][safi];
4117
4118 /* apply peer-group filter */
4119 if (peer->af_group[afi][safi])
4120 {
4121 gfilter = &peer->group->conf->filter[afi][safi];
4122
4123 if (gfilter->map[direct].name)
4124 {
4125 if (filter->map[direct].name)
4126 free (filter->map[direct].name);
4127 filter->map[direct].name = strdup (gfilter->map[direct].name);
4128 filter->map[direct].map = gfilter->map[direct].map;
4129 return 0;
4130 }
4131 }
4132
4133 if (filter->map[direct].name)
4134 free (filter->map[direct].name);
4135 filter->map[direct].name = NULL;
4136 filter->map[direct].map = NULL;
4137
4138 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4139 return 0;
4140
4141 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004142 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004143 {
4144 filter = &peer->filter[afi][safi];
4145
4146 if (! peer->af_group[afi][safi])
4147 continue;
4148
4149 if (filter->map[direct].name)
4150 free (filter->map[direct].name);
4151 filter->map[direct].name = NULL;
4152 filter->map[direct].map = NULL;
4153 }
4154 return 0;
4155}
4156
4157/* Set unsuppress-map to the peer. */
4158int
paulfd79ac92004-10-13 05:06:08 +00004159peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4160 const char *name)
paul718e3742002-12-13 20:15:29 +00004161{
4162 struct bgp_filter *filter;
4163 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004165
4166 if (! peer->afc[afi][safi])
4167 return BGP_ERR_PEER_INACTIVE;
4168
4169 if (peer_is_group_member (peer, afi, safi))
4170 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4171
4172 filter = &peer->filter[afi][safi];
4173
4174 if (filter->usmap.name)
4175 free (filter->usmap.name);
4176
4177 filter->usmap.name = strdup (name);
4178 filter->usmap.map = route_map_lookup_by_name (name);
4179
4180 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4181 return 0;
4182
4183 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004184 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004185 {
4186 filter = &peer->filter[afi][safi];
4187
4188 if (! peer->af_group[afi][safi])
4189 continue;
4190
4191 if (filter->usmap.name)
4192 free (filter->usmap.name);
4193 filter->usmap.name = strdup (name);
4194 filter->usmap.map = route_map_lookup_by_name (name);
4195 }
4196 return 0;
4197}
4198
4199/* Unset route-map from the peer. */
4200int
4201peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4202{
4203 struct bgp_filter *filter;
4204 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004205 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004206
4207 if (! peer->afc[afi][safi])
4208 return BGP_ERR_PEER_INACTIVE;
4209
4210 if (peer_is_group_member (peer, afi, safi))
4211 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4212
4213 filter = &peer->filter[afi][safi];
4214
4215 if (filter->usmap.name)
4216 free (filter->usmap.name);
4217 filter->usmap.name = NULL;
4218 filter->usmap.map = NULL;
4219
4220 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4221 return 0;
4222
4223 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004224 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004225 {
4226 filter = &peer->filter[afi][safi];
4227
4228 if (! peer->af_group[afi][safi])
4229 continue;
4230
4231 if (filter->usmap.name)
4232 free (filter->usmap.name);
4233 filter->usmap.name = NULL;
4234 filter->usmap.map = NULL;
4235 }
4236 return 0;
4237}
4238
4239int
4240peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004241 u_int32_t max, u_char threshold,
4242 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004243{
4244 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004245 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004246
4247 if (! peer->afc[afi][safi])
4248 return BGP_ERR_PEER_INACTIVE;
4249
4250 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4251 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004252 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004253 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004254 if (warning)
4255 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4256 else
4257 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4258
4259 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4260 return 0;
4261
4262 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004263 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004264 {
4265 if (! peer->af_group[afi][safi])
4266 continue;
4267
4268 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4269 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004270 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004271 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004272 if (warning)
4273 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4274 else
4275 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4276 }
4277 return 0;
4278}
4279
4280int
4281peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4282{
4283 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004284 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004285
4286 if (! peer->afc[afi][safi])
4287 return BGP_ERR_PEER_INACTIVE;
4288
4289 /* apply peer-group config */
4290 if (peer->af_group[afi][safi])
4291 {
4292 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4293 PEER_FLAG_MAX_PREFIX))
4294 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4295 else
4296 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4297
4298 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4299 PEER_FLAG_MAX_PREFIX_WARNING))
4300 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4301 else
4302 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4303
4304 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004305 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004306 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004307 return 0;
4308 }
4309
4310 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4311 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4312 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004313 peer->pmax_threshold[afi][safi] = 0;
4314 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004315
4316 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4317 return 0;
4318
4319 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004320 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004321 {
4322 if (! peer->af_group[afi][safi])
4323 continue;
4324
4325 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4326 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4327 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004328 peer->pmax_threshold[afi][safi] = 0;
4329 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004330 }
4331 return 0;
4332}
4333
4334int
4335peer_clear (struct peer *peer)
4336{
4337 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4338 {
hasso0a486e52005-02-01 20:57:17 +00004339 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4340 {
4341 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4342 if (peer->t_pmax_restart)
4343 {
4344 BGP_TIMER_OFF (peer->t_pmax_restart);
4345 if (BGP_DEBUG (events, EVENTS))
4346 zlog_debug ("%s Maximum-prefix restart timer canceled",
4347 peer->host);
4348 }
4349 BGP_EVENT_ADD (peer, BGP_Start);
4350 return 0;
4351 }
4352
paul718e3742002-12-13 20:15:29 +00004353 peer->v_start = BGP_INIT_START_TIMER;
4354 if (peer->status == Established)
4355 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4356 BGP_NOTIFY_CEASE_ADMIN_RESET);
4357 else
4358 BGP_EVENT_ADD (peer, BGP_Stop);
4359 }
4360 return 0;
4361}
4362
4363int
4364peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4365 enum bgp_clear_type stype)
4366{
4367 if (peer->status != Established)
4368 return 0;
4369
4370 if (! peer->afc[afi][safi])
4371 return BGP_ERR_AF_UNCONFIGURED;
4372
paulfee0f4c2004-09-13 05:12:46 +00004373 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4374 {
4375 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4376 return 0;
4377 bgp_check_local_routes_rsclient (peer, afi, safi);
4378 bgp_soft_reconfig_rsclient (peer, afi, safi);
4379 }
4380
paul718e3742002-12-13 20:15:29 +00004381 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4382 bgp_announce_route (peer, afi, safi);
4383
4384 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4385 {
4386 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4387 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4388 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4389 {
4390 struct bgp_filter *filter = &peer->filter[afi][safi];
4391 u_char prefix_type;
4392
4393 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4394 prefix_type = ORF_TYPE_PREFIX;
4395 else
4396 prefix_type = ORF_TYPE_PREFIX_OLD;
4397
4398 if (filter->plist[FILTER_IN].plist)
4399 {
4400 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4401 bgp_route_refresh_send (peer, afi, safi,
4402 prefix_type, REFRESH_DEFER, 1);
4403 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4404 REFRESH_IMMEDIATE, 0);
4405 }
4406 else
4407 {
4408 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4409 bgp_route_refresh_send (peer, afi, safi,
4410 prefix_type, REFRESH_IMMEDIATE, 1);
4411 else
4412 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4413 }
4414 return 0;
4415 }
4416 }
4417
4418 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4419 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4420 {
4421 /* If neighbor has soft reconfiguration inbound flag.
4422 Use Adj-RIB-In database. */
4423 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4424 bgp_soft_reconfig_in (peer, afi, safi);
4425 else
4426 {
4427 /* If neighbor has route refresh capability, send route refresh
4428 message to the peer. */
4429 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4430 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4431 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4432 else
4433 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4434 }
4435 }
4436 return 0;
4437}
4438
paulfd79ac92004-10-13 05:06:08 +00004439/* Display peer uptime.*/
4440/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004441char *
4442peer_uptime (time_t uptime2, char *buf, size_t len)
4443{
4444 time_t uptime1;
4445 struct tm *tm;
4446
4447 /* Check buffer length. */
4448 if (len < BGP_UPTIME_LEN)
4449 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004450 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004451 /* XXX: should return status instead of buf... */
4452 snprintf (buf, len, "<error> ");
4453 return buf;
paul718e3742002-12-13 20:15:29 +00004454 }
4455
4456 /* If there is no connection has been done before print `never'. */
4457 if (uptime2 == 0)
4458 {
4459 snprintf (buf, len, "never ");
4460 return buf;
4461 }
4462
4463 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004464 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004465 uptime1 -= uptime2;
4466 tm = gmtime (&uptime1);
4467
4468 /* Making formatted timer strings. */
4469#define ONE_DAY_SECOND 60*60*24
4470#define ONE_WEEK_SECOND 60*60*24*7
4471
4472 if (uptime1 < ONE_DAY_SECOND)
4473 snprintf (buf, len, "%02d:%02d:%02d",
4474 tm->tm_hour, tm->tm_min, tm->tm_sec);
4475 else if (uptime1 < ONE_WEEK_SECOND)
4476 snprintf (buf, len, "%dd%02dh%02dm",
4477 tm->tm_yday, tm->tm_hour, tm->tm_min);
4478 else
4479 snprintf (buf, len, "%02dw%dd%02dh",
4480 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4481 return buf;
4482}
4483
paul94f2b392005-06-28 12:44:16 +00004484static void
paul718e3742002-12-13 20:15:29 +00004485bgp_config_write_filter (struct vty *vty, struct peer *peer,
4486 afi_t afi, safi_t safi)
4487{
4488 struct bgp_filter *filter;
4489 struct bgp_filter *gfilter = NULL;
4490 char *addr;
4491 int in = FILTER_IN;
4492 int out = FILTER_OUT;
4493
4494 addr = peer->host;
4495 filter = &peer->filter[afi][safi];
4496 if (peer->af_group[afi][safi])
4497 gfilter = &peer->group->conf->filter[afi][safi];
4498
4499 /* distribute-list. */
4500 if (filter->dlist[in].name)
4501 if (! gfilter || ! gfilter->dlist[in].name
4502 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4503 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4504 filter->dlist[in].name, VTY_NEWLINE);
4505 if (filter->dlist[out].name && ! gfilter)
4506 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4507 filter->dlist[out].name, VTY_NEWLINE);
4508
4509 /* prefix-list. */
4510 if (filter->plist[in].name)
4511 if (! gfilter || ! gfilter->plist[in].name
4512 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4513 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4514 filter->plist[in].name, VTY_NEWLINE);
4515 if (filter->plist[out].name && ! gfilter)
4516 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4517 filter->plist[out].name, VTY_NEWLINE);
4518
4519 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004520 if (filter->map[RMAP_IN].name)
4521 if (! gfilter || ! gfilter->map[RMAP_IN].name
4522 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004523 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004524 filter->map[RMAP_IN].name, VTY_NEWLINE);
4525 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004526 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004527 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4528 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4529 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4530 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4531 if (filter->map[RMAP_EXPORT].name)
4532 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4533 || strcmp (filter->map[RMAP_EXPORT].name,
4534 gfilter->map[RMAP_EXPORT].name) != 0)
4535 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4536 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004537
4538 /* unsuppress-map */
4539 if (filter->usmap.name && ! gfilter)
4540 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4541 filter->usmap.name, VTY_NEWLINE);
4542
4543 /* filter-list. */
4544 if (filter->aslist[in].name)
4545 if (! gfilter || ! gfilter->aslist[in].name
4546 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4547 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4548 filter->aslist[in].name, VTY_NEWLINE);
4549 if (filter->aslist[out].name && ! gfilter)
4550 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4551 filter->aslist[out].name, VTY_NEWLINE);
4552}
4553
4554/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004555static void
paul718e3742002-12-13 20:15:29 +00004556bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4557 struct peer *peer, afi_t afi, safi_t safi)
4558{
4559 struct bgp_filter *filter;
4560 struct peer *g_peer = NULL;
4561 char buf[SU_ADDRSTRLEN];
4562 char *addr;
4563
4564 filter = &peer->filter[afi][safi];
4565 addr = peer->host;
4566 if (peer_group_active (peer))
4567 g_peer = peer->group->conf;
4568
4569 /************************************
4570 ****** Global to the neighbor ******
4571 ************************************/
4572 if (afi == AFI_IP && safi == SAFI_UNICAST)
4573 {
4574 /* remote-as. */
4575 if (! peer_group_active (peer))
4576 {
4577 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4578 vty_out (vty, " neighbor %s peer-group%s", addr,
4579 VTY_NEWLINE);
4580 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004581 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004582 VTY_NEWLINE);
4583 }
4584 else
4585 {
4586 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004587 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004588 VTY_NEWLINE);
4589 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4590 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4591 peer->group->name, VTY_NEWLINE);
4592 }
4593
4594 /* local-as. */
4595 if (peer->change_local_as)
4596 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004597 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004598 peer->change_local_as,
4599 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4600 " no-prepend" : "", VTY_NEWLINE);
4601
4602 /* Description. */
4603 if (peer->desc)
4604 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4605 VTY_NEWLINE);
4606
4607 /* Shutdown. */
4608 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4609 if (! peer_group_active (peer) ||
4610 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4611 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4612
Paul Jakma0df7c912008-07-21 21:02:49 +00004613 /* Password. */
4614 if (peer->password)
4615 if (!peer_group_active (peer)
4616 || ! g_peer->password
4617 || strcmp (peer->password, g_peer->password) != 0)
4618 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4619 VTY_NEWLINE);
4620
paul718e3742002-12-13 20:15:29 +00004621 /* BGP port. */
4622 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004623 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004624 VTY_NEWLINE);
4625
4626 /* Local interface name. */
4627 if (peer->ifname)
4628 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4629 VTY_NEWLINE);
4630
4631 /* Passive. */
4632 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4633 if (! peer_group_active (peer) ||
4634 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4635 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4636
4637 /* EBGP multihop. */
4638 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4639 if (! peer_group_active (peer) ||
4640 g_peer->ttl != peer->ttl)
4641 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4642 VTY_NEWLINE);
4643
hasso6ffd2072005-02-02 14:50:11 +00004644 /* disable-connected-check. */
4645 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004646 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004647 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4648 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004649
4650 /* Update-source. */
4651 if (peer->update_if)
4652 if (! peer_group_active (peer) || ! g_peer->update_if
4653 || strcmp (g_peer->update_if, peer->update_if) != 0)
4654 vty_out (vty, " neighbor %s update-source %s%s", addr,
4655 peer->update_if, VTY_NEWLINE);
4656 if (peer->update_source)
4657 if (! peer_group_active (peer) || ! g_peer->update_source
4658 || sockunion_cmp (g_peer->update_source,
4659 peer->update_source) != 0)
4660 vty_out (vty, " neighbor %s update-source %s%s", addr,
4661 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4662 VTY_NEWLINE);
4663
paul718e3742002-12-13 20:15:29 +00004664 /* advertisement-interval */
4665 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4666 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4667 addr, peer->v_routeadv, VTY_NEWLINE);
4668
4669 /* timers. */
4670 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4671 && ! peer_group_active (peer))
4672 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4673 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4674
4675 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4676 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4677 peer->connect, VTY_NEWLINE);
4678
4679 /* Default weight. */
4680 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4681 if (! peer_group_active (peer) ||
4682 g_peer->weight != peer->weight)
4683 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4684 VTY_NEWLINE);
4685
paul718e3742002-12-13 20:15:29 +00004686 /* Dynamic capability. */
4687 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4688 if (! peer_group_active (peer) ||
4689 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4690 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4691 VTY_NEWLINE);
4692
4693 /* dont capability negotiation. */
4694 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4695 if (! peer_group_active (peer) ||
4696 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4697 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4698 VTY_NEWLINE);
4699
4700 /* override capability negotiation. */
4701 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4702 if (! peer_group_active (peer) ||
4703 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4704 vty_out (vty, " neighbor %s override-capability%s", addr,
4705 VTY_NEWLINE);
4706
4707 /* strict capability negotiation. */
4708 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4709 if (! peer_group_active (peer) ||
4710 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4711 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4712 VTY_NEWLINE);
4713
4714 if (! peer_group_active (peer))
4715 {
4716 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4717 {
4718 if (peer->afc[AFI_IP][SAFI_UNICAST])
4719 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4720 }
4721 else
4722 {
4723 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4724 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4725 }
4726 }
4727 }
4728
4729
4730 /************************************
4731 ****** Per AF to the neighbor ******
4732 ************************************/
4733
4734 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4735 {
4736 if (peer->af_group[afi][safi])
4737 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4738 peer->group->name, VTY_NEWLINE);
4739 else
4740 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4741 }
4742
4743 /* ORF capability. */
4744 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4745 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4746 if (! peer->af_group[afi][safi])
4747 {
4748 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4749
4750 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4751 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4752 vty_out (vty, " both");
4753 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4754 vty_out (vty, " send");
4755 else
4756 vty_out (vty, " receive");
4757 vty_out (vty, "%s", VTY_NEWLINE);
4758 }
4759
4760 /* Route reflector client. */
4761 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4762 && ! peer->af_group[afi][safi])
4763 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4764 VTY_NEWLINE);
4765
4766 /* Nexthop self. */
4767 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4768 && ! peer->af_group[afi][safi])
4769 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4770
4771 /* Remove private AS. */
4772 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4773 && ! peer->af_group[afi][safi])
4774 vty_out (vty, " neighbor %s remove-private-AS%s",
4775 addr, VTY_NEWLINE);
4776
4777 /* send-community print. */
4778 if (! peer->af_group[afi][safi])
4779 {
4780 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4781 {
4782 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4783 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4784 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4785 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4786 vty_out (vty, " neighbor %s send-community extended%s",
4787 addr, VTY_NEWLINE);
4788 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4789 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4790 }
4791 else
4792 {
4793 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4794 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4795 vty_out (vty, " no neighbor %s send-community both%s",
4796 addr, VTY_NEWLINE);
4797 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4798 vty_out (vty, " no neighbor %s send-community extended%s",
4799 addr, VTY_NEWLINE);
4800 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4801 vty_out (vty, " no neighbor %s send-community%s",
4802 addr, VTY_NEWLINE);
4803 }
4804 }
4805
4806 /* Default information */
4807 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4808 && ! peer->af_group[afi][safi])
4809 {
4810 vty_out (vty, " neighbor %s default-originate", addr);
4811 if (peer->default_rmap[afi][safi].name)
4812 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4813 vty_out (vty, "%s", VTY_NEWLINE);
4814 }
4815
4816 /* Soft reconfiguration inbound. */
4817 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4818 if (! peer->af_group[afi][safi] ||
4819 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4820 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4821 VTY_NEWLINE);
4822
4823 /* maximum-prefix. */
4824 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4825 if (! peer->af_group[afi][safi]
4826 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004827 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004828 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4829 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004830 {
hasso0a486e52005-02-01 20:57:17 +00004831 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4832 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4833 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4834 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4835 vty_out (vty, " warning-only");
4836 if (peer->pmax_restart[afi][safi])
4837 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4838 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004839 }
paul718e3742002-12-13 20:15:29 +00004840
4841 /* Route server client. */
4842 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4843 && ! peer->af_group[afi][safi])
4844 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4845
4846 /* Allow AS in. */
4847 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4848 if (! peer_group_active (peer)
4849 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4850 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4851 {
4852 if (peer->allowas_in[afi][safi] == 3)
4853 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4854 else
4855 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4856 peer->allowas_in[afi][safi], VTY_NEWLINE);
4857 }
4858
4859 /* Filter. */
4860 bgp_config_write_filter (vty, peer, afi, safi);
4861
4862 /* atribute-unchanged. */
4863 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4864 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4865 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4866 && ! peer->af_group[afi][safi])
4867 {
4868 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4869 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4870 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4871 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4872 else
4873 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4874 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4875 " as-path" : "",
4876 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4877 " next-hop" : "",
4878 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4879 " med" : "", VTY_NEWLINE);
4880 }
4881}
4882
4883/* Display "address-family" configuration header. */
4884void
4885bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4886 int *write)
4887{
4888 if (*write)
4889 return;
4890
4891 if (afi == AFI_IP && safi == SAFI_UNICAST)
4892 return;
4893
4894 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4895
4896 if (afi == AFI_IP)
4897 {
4898 if (safi == SAFI_MULTICAST)
4899 vty_out (vty, "ipv4 multicast");
4900 else if (safi == SAFI_MPLS_VPN)
4901 vty_out (vty, "vpnv4 unicast");
4902 }
4903 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004904 {
4905 vty_out (vty, "ipv6");
4906
4907 if (safi == SAFI_MULTICAST)
4908 vty_out (vty, " multicast");
4909 }
paul718e3742002-12-13 20:15:29 +00004910
4911 vty_out (vty, "%s", VTY_NEWLINE);
4912
4913 *write = 1;
4914}
4915
4916/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004917static int
paul718e3742002-12-13 20:15:29 +00004918bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4919 safi_t safi)
4920{
4921 int write = 0;
4922 struct peer *peer;
4923 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004924 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004925
4926 bgp_config_write_network (vty, bgp, afi, safi, &write);
4927
4928 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4929
paul1eb8ef22005-04-07 07:30:20 +00004930 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004931 {
4932 if (group->conf->afc[afi][safi])
4933 {
4934 bgp_config_write_family_header (vty, afi, safi, &write);
4935 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4936 }
4937 }
paul1eb8ef22005-04-07 07:30:20 +00004938 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004939 {
4940 if (peer->afc[afi][safi])
4941 {
4942 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4943 {
4944 bgp_config_write_family_header (vty, afi, safi, &write);
4945 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4946 }
4947 }
4948 }
4949 if (write)
4950 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4951
4952 return write;
4953}
4954
4955int
4956bgp_config_write (struct vty *vty)
4957{
4958 int write = 0;
4959 struct bgp *bgp;
4960 struct peer_group *group;
4961 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004962 struct listnode *node, *nnode;
4963 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004964
4965 /* BGP Multiple instance. */
4966 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4967 {
4968 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4969 write++;
4970 }
4971
4972 /* BGP Config type. */
4973 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4974 {
4975 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4976 write++;
4977 }
4978
4979 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004980 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004981 {
4982 if (write)
4983 vty_out (vty, "!%s", VTY_NEWLINE);
4984
4985 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004986 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00004987
4988 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4989 {
4990 if (bgp->name)
4991 vty_out (vty, " view %s", bgp->name);
4992 }
4993 vty_out (vty, "%s", VTY_NEWLINE);
4994
4995 /* No Synchronization */
4996 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4997 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4998
4999 /* BGP fast-external-failover. */
5000 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5001 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5002
5003 /* BGP router ID. */
5004 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5005 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5006 VTY_NEWLINE);
5007
paul848973c2003-08-13 00:32:49 +00005008 /* BGP log-neighbor-changes. */
5009 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5010 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5011
paul718e3742002-12-13 20:15:29 +00005012 /* BGP configuration. */
5013 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5014 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5015
5016 /* BGP default ipv4-unicast. */
5017 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5018 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5019
5020 /* BGP default local-preference. */
5021 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5022 vty_out (vty, " bgp default local-preference %d%s",
5023 bgp->default_local_pref, VTY_NEWLINE);
5024
5025 /* BGP client-to-client reflection. */
5026 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5027 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5028
5029 /* BGP cluster ID. */
5030 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5031 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5032 VTY_NEWLINE);
5033
hassoe0701b72004-05-20 09:19:34 +00005034 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005035 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005036 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5037 VTY_NEWLINE);
5038
5039 /* Confederation peer */
5040 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005041 {
hassoe0701b72004-05-20 09:19:34 +00005042 int i;
paul718e3742002-12-13 20:15:29 +00005043
hassoe0701b72004-05-20 09:19:34 +00005044 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005045
hassoe0701b72004-05-20 09:19:34 +00005046 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005047 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005048
hassoe0701b72004-05-20 09:19:34 +00005049 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005050 }
5051
5052 /* BGP enforce-first-as. */
5053 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5054 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5055
5056 /* BGP deterministic-med. */
5057 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5058 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005059
5060 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005061 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5062 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5063 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005064 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5065 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5066
paul718e3742002-12-13 20:15:29 +00005067 /* BGP bestpath method. */
5068 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5069 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005070 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5071 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005072 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5073 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5074 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5075 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5076 {
5077 vty_out (vty, " bgp bestpath med");
5078 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5079 vty_out (vty, " confed");
5080 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5081 vty_out (vty, " missing-as-worst");
5082 vty_out (vty, "%s", VTY_NEWLINE);
5083 }
5084
5085 /* BGP network import check. */
5086 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5087 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5088
5089 /* BGP scan interval. */
5090 bgp_config_write_scan_time (vty);
5091
5092 /* BGP flag dampening. */
5093 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5094 BGP_CONFIG_DAMPENING))
5095 bgp_config_write_damp (vty);
5096
5097 /* BGP static route configuration. */
5098 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5099
5100 /* BGP redistribute configuration. */
5101 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5102
5103 /* BGP timers configuration. */
5104 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5105 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5106 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5107 bgp->default_holdtime, VTY_NEWLINE);
5108
5109 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005110 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005111 {
5112 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5113 }
5114
5115 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005116 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005117 {
5118 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5119 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5120 }
5121
5122 /* Distance configuration. */
5123 bgp_config_write_distance (vty, bgp);
5124
5125 /* No auto-summary */
5126 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5127 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5128
5129 /* IPv4 multicast configuration. */
5130 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5131
5132 /* IPv4 VPN configuration. */
5133 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5134
5135 /* IPv6 unicast configuration. */
5136 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5137
Paul Jakma37a217a2007-04-10 19:20:29 +00005138 /* IPv6 multicast configuration. */
5139 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5140
paul718e3742002-12-13 20:15:29 +00005141 write++;
5142 }
5143 return write;
5144}
5145
5146void
paul94f2b392005-06-28 12:44:16 +00005147bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005148{
5149 memset (&bgp_master, 0, sizeof (struct bgp_master));
5150
5151 bm = &bgp_master;
5152 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005153 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005154 bm->port = BGP_PORT_DEFAULT;
5155 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005156 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005157}
paul200df112005-06-01 11:17:05 +00005158
paul718e3742002-12-13 20:15:29 +00005159
5160void
paul94f2b392005-06-28 12:44:16 +00005161bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005162{
paul718e3742002-12-13 20:15:29 +00005163 /* BGP VTY commands installation. */
5164 bgp_vty_init ();
5165
paul718e3742002-12-13 20:15:29 +00005166 /* Init zebra. */
5167 bgp_zebra_init ();
5168
5169 /* BGP inits. */
5170 bgp_attr_init ();
5171 bgp_debug_init ();
5172 bgp_dump_init ();
5173 bgp_route_init ();
5174 bgp_route_map_init ();
5175 bgp_scan_init ();
5176 bgp_mplsvpn_init ();
5177
5178 /* Access list initialize. */
5179 access_list_init ();
5180 access_list_add_hook (peer_distribute_update);
5181 access_list_delete_hook (peer_distribute_update);
5182
5183 /* Filter list initialize. */
5184 bgp_filter_init ();
5185 as_list_add_hook (peer_aslist_update);
5186 as_list_delete_hook (peer_aslist_update);
5187
5188 /* Prefix list initialize.*/
5189 prefix_list_init ();
5190 prefix_list_add_hook (peer_prefix_list_update);
5191 prefix_list_delete_hook (peer_prefix_list_update);
5192
5193 /* Community list initialize. */
5194 bgp_clist = community_list_init ();
5195
5196#ifdef HAVE_SNMP
5197 bgp_snmp_init ();
5198#endif /* HAVE_SNMP */
5199}
paul545acaf2004-04-20 15:13:15 +00005200
5201void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005202bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005203{
paul545acaf2004-04-20 15:13:15 +00005204 struct bgp *bgp;
5205 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005206 struct listnode *node, *nnode;
5207 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005208
paul1eb8ef22005-04-07 07:30:20 +00005209 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5210 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005211 if (peer->status == Established)
5212 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5213 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005214
paul545acaf2004-04-20 15:13:15 +00005215 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005216
paule210cf92005-06-15 19:15:35 +00005217 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005218 {
5219 work_queue_free (bm->process_main_queue);
5220 bm->process_main_queue = NULL;
5221 }
paule210cf92005-06-15 19:15:35 +00005222 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005223 {
5224 work_queue_free (bm->process_rsclient_queue);
5225 bm->process_rsclient_queue = NULL;
5226 }
paul545acaf2004-04-20 15:13:15 +00005227}