blob: e8038553ababffbe894b32ad1bec00c21e804f58 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
hasso18a6dce2004-10-03 18:18:34 +000067extern struct in_addr router_id_zebra;
68
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000088 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000107 }
108 return 0;
109}
110
111int
112bgp_option_check (int flag)
113{
114 return CHECK_FLAG (bm->options, flag);
115}
116
117/* BGP flag manipulation. */
118int
119bgp_flag_set (struct bgp *bgp, int flag)
120{
121 SET_FLAG (bgp->flags, flag);
122 return 0;
123}
124
125int
126bgp_flag_unset (struct bgp *bgp, int flag)
127{
128 UNSET_FLAG (bgp->flags, flag);
129 return 0;
130}
131
132int
133bgp_flag_check (struct bgp *bgp, int flag)
134{
135 return CHECK_FLAG (bgp->flags, flag);
136}
137
138/* Internal function to set BGP structure configureation flag. */
139static void
140bgp_config_set (struct bgp *bgp, int config)
141{
142 SET_FLAG (bgp->config, config);
143}
144
145static void
146bgp_config_unset (struct bgp *bgp, int config)
147{
148 UNSET_FLAG (bgp->config, config);
149}
150
151static int
152bgp_config_check (struct bgp *bgp, int config)
153{
154 return CHECK_FLAG (bgp->config, config);
155}
156
157/* Set BGP router identifier. */
158int
159bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
160{
161 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000163
164 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
165 && IPV4_ADDR_SAME (&bgp->router_id, id))
166 return 0;
167
168 IPV4_ADDR_COPY (&bgp->router_id, id);
169 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
170
171 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000173 {
174 IPV4_ADDR_COPY (&peer->local_id, id);
175
176 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000177 {
178 peer->last_reset = PEER_DOWN_RID_CHANGE;
179 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
180 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
181 }
paul718e3742002-12-13 20:15:29 +0000182 }
183 return 0;
184}
185
paul718e3742002-12-13 20:15:29 +0000186/* BGP's cluster-id control. */
187int
188bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
189{
190 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000191 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000192
193 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
194 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
195 return 0;
196
197 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
198 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
199
200 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000202 {
203 if (peer_sort (peer) != BGP_PEER_IBGP)
204 continue;
205
206 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000207 {
208 peer->last_reset = PEER_DOWN_CLID_CHANGE;
209 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
210 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
211 }
paul718e3742002-12-13 20:15:29 +0000212 }
213 return 0;
214}
215
216int
217bgp_cluster_id_unset (struct bgp *bgp)
218{
219 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000220 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000221
222 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
223 return 0;
224
225 bgp->cluster_id.s_addr = 0;
226 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
227
228 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000229 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000230 {
231 if (peer_sort (peer) != BGP_PEER_IBGP)
232 continue;
233
234 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000235 {
236 peer->last_reset = PEER_DOWN_CLID_CHANGE;
237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
239 }
paul718e3742002-12-13 20:15:29 +0000240 }
241 return 0;
242}
243
Stephen Hemminger65957882010-01-15 16:22:10 +0300244/* time_t value that is monotonicly increasing
245 * and uneffected by adjustments to system clock
246 */
247time_t bgp_clock (void)
248{
249 struct timeval tv;
250
251 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
252 return tv.tv_sec;
253}
254
paul718e3742002-12-13 20:15:29 +0000255/* BGP timer configuration. */
256int
257bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
258{
259 bgp->default_keepalive = (keepalive < holdtime / 3
260 ? keepalive : holdtime / 3);
261 bgp->default_holdtime = holdtime;
262
263 return 0;
264}
265
266int
267bgp_timers_unset (struct bgp *bgp)
268{
269 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
270 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
271
272 return 0;
273}
274
275/* BGP confederation configuration. */
276int
277bgp_confederation_id_set (struct bgp *bgp, as_t as)
278{
279 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000280 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000281 int already_confed;
282
283 if (as == 0)
284 return BGP_ERR_INVALID_AS;
285
286 /* Remember - were we doing confederation before? */
287 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
288 bgp->confed_id = as;
289 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
290
291 /* If we were doing confederation already, this is just an external
292 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
293 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000294 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000295 {
296 /* We're looking for peers who's AS is not local or part of our
297 confederation. */
298 if (already_confed)
299 {
300 if (peer_sort (peer) == BGP_PEER_EBGP)
301 {
302 peer->local_as = as;
303 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000304 {
305 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
306 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
307 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
308 }
309
paul718e3742002-12-13 20:15:29 +0000310 else
311 BGP_EVENT_ADD (peer, BGP_Stop);
312 }
313 }
314 else
315 {
316 /* Not doign confederation before, so reset every non-local
317 session */
318 if (peer_sort (peer) != BGP_PEER_IBGP)
319 {
320 /* Reset the local_as to be our EBGP one */
321 if (peer_sort (peer) == BGP_PEER_EBGP)
322 peer->local_as = as;
323 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000324 {
325 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
326 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
327 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
328 }
paul718e3742002-12-13 20:15:29 +0000329 else
330 BGP_EVENT_ADD (peer, BGP_Stop);
331 }
332 }
333 }
334 return 0;
335}
336
337int
338bgp_confederation_id_unset (struct bgp *bgp)
339{
340 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000341 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000342
343 bgp->confed_id = 0;
344 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
345
paul1eb8ef22005-04-07 07:30:20 +0000346 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000347 {
348 /* We're looking for peers who's AS is not local */
349 if (peer_sort (peer) != BGP_PEER_IBGP)
350 {
351 peer->local_as = bgp->as;
352 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000353 {
354 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
355 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
356 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
357 }
358
paul718e3742002-12-13 20:15:29 +0000359 else
360 BGP_EVENT_ADD (peer, BGP_Stop);
361 }
362 }
363 return 0;
364}
365
366/* Is an AS part of the confed or not? */
367int
368bgp_confederation_peers_check (struct bgp *bgp, as_t as)
369{
370 int i;
371
372 if (! bgp)
373 return 0;
374
375 for (i = 0; i < bgp->confed_peers_cnt; i++)
376 if (bgp->confed_peers[i] == as)
377 return 1;
378
379 return 0;
380}
381
382/* Add an AS to the confederation set. */
383int
384bgp_confederation_peers_add (struct bgp *bgp, as_t as)
385{
386 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000387 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000388
389 if (! bgp)
390 return BGP_ERR_INVALID_BGP;
391
392 if (bgp->as == as)
393 return BGP_ERR_INVALID_AS;
394
395 if (bgp_confederation_peers_check (bgp, as))
396 return -1;
397
398 if (bgp->confed_peers)
399 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
400 bgp->confed_peers,
401 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
402 else
403 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
404 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
405
406 bgp->confed_peers[bgp->confed_peers_cnt] = as;
407 bgp->confed_peers_cnt++;
408
409 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
410 {
paul1eb8ef22005-04-07 07:30:20 +0000411 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000412 {
413 if (peer->as == as)
414 {
415 peer->local_as = bgp->as;
416 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000417 {
418 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
419 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
420 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
421 }
paul718e3742002-12-13 20:15:29 +0000422 else
423 BGP_EVENT_ADD (peer, BGP_Stop);
424 }
425 }
426 }
427 return 0;
428}
429
430/* Delete an AS from the confederation set. */
431int
432bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
433{
434 int i;
435 int j;
436 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000437 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000438
439 if (! bgp)
440 return -1;
441
442 if (! bgp_confederation_peers_check (bgp, as))
443 return -1;
444
445 for (i = 0; i < bgp->confed_peers_cnt; i++)
446 if (bgp->confed_peers[i] == as)
447 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
448 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
449
450 bgp->confed_peers_cnt--;
451
452 if (bgp->confed_peers_cnt == 0)
453 {
454 if (bgp->confed_peers)
455 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
456 bgp->confed_peers = NULL;
457 }
458 else
459 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
460 bgp->confed_peers,
461 bgp->confed_peers_cnt * sizeof (as_t));
462
463 /* Now reset any peer who's remote AS has just been removed from the
464 CONFED */
465 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
466 {
paul1eb8ef22005-04-07 07:30:20 +0000467 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000468 {
469 if (peer->as == as)
470 {
471 peer->local_as = bgp->confed_id;
472 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000473 {
474 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
475 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
476 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
477 }
paul718e3742002-12-13 20:15:29 +0000478 else
479 BGP_EVENT_ADD (peer, BGP_Stop);
480 }
481 }
482 }
483
484 return 0;
485}
486
487/* Local preference configuration. */
488int
489bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
490{
491 if (! bgp)
492 return -1;
493
paul718e3742002-12-13 20:15:29 +0000494 bgp->default_local_pref = local_pref;
495
496 return 0;
497}
498
499int
500bgp_default_local_preference_unset (struct bgp *bgp)
501{
502 if (! bgp)
503 return -1;
504
paul718e3742002-12-13 20:15:29 +0000505 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
506
507 return 0;
508}
509
paulfee0f4c2004-09-13 05:12:46 +0000510/* If peer is RSERVER_CLIENT in at least one address family and is not member
511 of a peer_group for that family, return 1.
512 Used to check wether the peer is included in list bgp->rsclient. */
513int
514peer_rsclient_active (struct peer *peer)
515{
516 int i;
517 int j;
518
519 for (i=AFI_IP; i < AFI_MAX; i++)
520 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
521 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
522 && ! peer->af_group[i][j])
523 return 1;
524 return 0;
525}
526
pauleb821182004-05-01 08:44:08 +0000527/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000528static int
529peer_cmp (struct peer *p1, struct peer *p2)
530{
pauleb821182004-05-01 08:44:08 +0000531 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000532}
533
534int
535peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
536{
537 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
538}
539
540/* Reset all address family specific configuration. */
541static void
542peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
543{
544 int i;
545 struct bgp_filter *filter;
546 char orf_name[BUFSIZ];
547
548 filter = &peer->filter[afi][safi];
549
550 /* Clear neighbor filter and route-map */
551 for (i = FILTER_IN; i < FILTER_MAX; i++)
552 {
553 if (filter->dlist[i].name)
554 {
555 free (filter->dlist[i].name);
556 filter->dlist[i].name = NULL;
557 }
558 if (filter->plist[i].name)
559 {
560 free (filter->plist[i].name);
561 filter->plist[i].name = NULL;
562 }
563 if (filter->aslist[i].name)
564 {
565 free (filter->aslist[i].name);
566 filter->aslist[i].name = NULL;
567 }
paulfee0f4c2004-09-13 05:12:46 +0000568 }
569 for (i = RMAP_IN; i < RMAP_MAX; i++)
570 {
paul718e3742002-12-13 20:15:29 +0000571 if (filter->map[i].name)
572 {
573 free (filter->map[i].name);
574 filter->map[i].name = NULL;
575 }
576 }
577
578 /* Clear unsuppress map. */
579 if (filter->usmap.name)
580 free (filter->usmap.name);
581 filter->usmap.name = NULL;
582 filter->usmap.map = NULL;
583
584 /* Clear neighbor's all address family flags. */
585 peer->af_flags[afi][safi] = 0;
586
587 /* Clear neighbor's all address family sflags. */
588 peer->af_sflags[afi][safi] = 0;
589
590 /* Clear neighbor's all address family capabilities. */
591 peer->af_cap[afi][safi] = 0;
592
593 /* Clear ORF info */
594 peer->orf_plist[afi][safi] = NULL;
595 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
596 prefix_bgp_orf_remove_all (orf_name);
597
598 /* Set default neighbor send-community. */
599 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
600 {
601 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
602 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
603 }
604
605 /* Clear neighbor default_originate_rmap */
606 if (peer->default_rmap[afi][safi].name)
607 free (peer->default_rmap[afi][safi].name);
608 peer->default_rmap[afi][safi].name = NULL;
609 peer->default_rmap[afi][safi].map = NULL;
610
611 /* Clear neighbor maximum-prefix */
612 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000613 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000614}
615
616/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000617static void
paul718e3742002-12-13 20:15:29 +0000618peer_global_config_reset (struct peer *peer)
619{
620 peer->weight = 0;
621 peer->change_local_as = 0;
622 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
623 if (peer->update_source)
624 {
625 sockunion_free (peer->update_source);
626 peer->update_source = NULL;
627 }
628 if (peer->update_if)
629 {
630 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
631 peer->update_if = NULL;
632 }
633
634 if (peer_sort (peer) == BGP_PEER_IBGP)
635 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
636 else
637 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
638
639 peer->flags = 0;
640 peer->config = 0;
641 peer->holdtime = 0;
642 peer->keepalive = 0;
643 peer->connect = 0;
644 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
645}
646
647/* Check peer's AS number and determin is this peer IBGP or EBGP */
648int
649peer_sort (struct peer *peer)
650{
651 struct bgp *bgp;
652
653 bgp = peer->bgp;
654
655 /* Peer-group */
656 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
657 {
658 if (peer->as)
659 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
660 else
661 {
662 struct peer *peer1;
663 peer1 = listnode_head (peer->group->peer);
664 if (peer1)
665 return (peer1->local_as == peer1->as
666 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
667 }
668 return BGP_PEER_INTERNAL;
669 }
670
671 /* Normal peer */
672 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
673 {
674 if (peer->local_as == 0)
675 return BGP_PEER_INTERNAL;
676
677 if (peer->local_as == peer->as)
678 {
679 if (peer->local_as == bgp->confed_id)
680 return BGP_PEER_EBGP;
681 else
682 return BGP_PEER_IBGP;
683 }
684
685 if (bgp_confederation_peers_check (bgp, peer->as))
686 return BGP_PEER_CONFED;
687
688 return BGP_PEER_EBGP;
689 }
690 else
691 {
692 return (peer->local_as == 0
693 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
694 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
695 }
696}
697
paul200df112005-06-01 11:17:05 +0000698static inline void
699peer_free (struct peer *peer)
700{
Paul Jakmaca058a32006-09-14 02:58:49 +0000701 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700702
703 bgp_unlock(peer->bgp);
704
Paul Jakmaca058a32006-09-14 02:58:49 +0000705 /* this /ought/ to have been done already through bgp_stop earlier,
706 * but just to be sure..
707 */
708 bgp_timer_set (peer);
709 BGP_READ_OFF (peer->t_read);
710 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000711 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000712
paul200df112005-06-01 11:17:05 +0000713 if (peer->desc)
714 XFREE (MTYPE_PEER_DESC, peer->desc);
715
716 /* Free allocated host character. */
717 if (peer->host)
718 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
719
720 /* Update source configuration. */
721 if (peer->update_source)
722 sockunion_free (peer->update_source);
723
724 if (peer->update_if)
725 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000726
727 if (peer->clear_node_queue)
728 work_queue_free (peer->clear_node_queue);
729
Paul Jakmaca058a32006-09-14 02:58:49 +0000730 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000731 memset (peer, 0, sizeof (struct peer));
732
733 XFREE (MTYPE_BGP_PEER, peer);
734}
735
736/* increase reference count on a struct peer */
737struct peer *
738peer_lock (struct peer *peer)
739{
740 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000741
paul200df112005-06-01 11:17:05 +0000742 peer->lock++;
743
744 return peer;
745}
746
747/* decrease reference count on a struct peer
748 * struct peer is freed and NULL returned if last reference
749 */
750struct peer *
751peer_unlock (struct peer *peer)
752{
753 assert (peer && (peer->lock > 0));
754
755 peer->lock--;
756
757 if (peer->lock == 0)
758 {
759#if 0
760 zlog_debug ("unlocked and freeing");
761 zlog_backtrace (LOG_DEBUG);
762#endif
763 peer_free (peer);
764 return NULL;
765 }
766
767#if 0
768 if (peer->lock == 1)
769 {
770 zlog_debug ("unlocked to 1");
771 zlog_backtrace (LOG_DEBUG);
772 }
773#endif
774
775 return peer;
776}
777
778/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000779static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000780peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000781{
782 afi_t afi;
783 safi_t safi;
784 struct peer *peer;
785 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000786
787 /* bgp argument is absolutely required */
788 assert (bgp);
789 if (!bgp)
790 return NULL;
791
paul718e3742002-12-13 20:15:29 +0000792 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000793 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000794
795 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000796 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000797 peer->v_start = BGP_INIT_START_TIMER;
798 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
799 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
800 peer->status = Idle;
801 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000802 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000803 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000804 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000805 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700806 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000807
808 /* Set default flags. */
809 for (afi = AFI_IP; afi < AFI_MAX; afi++)
810 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
811 {
812 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
813 {
814 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
815 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
816 }
817 peer->orf_plist[afi][safi] = NULL;
818 }
819 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
820
821 /* Create buffers. */
822 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
823 peer->obuf = stream_fifo_new ();
824 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
825
826 bgp_sync_init (peer);
827
828 /* Get service port number. */
829 sp = getservbyname ("bgp", "tcp");
830 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
831
832 return peer;
833}
834
835/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000836static struct peer *
paul718e3742002-12-13 20:15:29 +0000837peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
838 as_t remote_as, afi_t afi, safi_t safi)
839{
840 int active;
841 struct peer *peer;
842 char buf[SU_ADDRSTRLEN];
843
Paul Jakma6f585442006-10-22 19:13:07 +0000844 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000845 peer->su = *su;
846 peer->local_as = local_as;
847 peer->as = remote_as;
848 peer->local_id = bgp->router_id;
849 peer->v_holdtime = bgp->default_holdtime;
850 peer->v_keepalive = bgp->default_keepalive;
851 if (peer_sort (peer) == BGP_PEER_IBGP)
852 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
853 else
854 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000855
856 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000857 listnode_add_sort (bgp->peer, peer);
858
859 active = peer_active (peer);
860
861 if (afi && safi)
862 peer->afc[afi][safi] = 1;
863
Stephen Hemminger65957882010-01-15 16:22:10 +0300864 /* Last read and reset time set */
865 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000866
paul718e3742002-12-13 20:15:29 +0000867 /* Default TTL set. */
868 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
869
870 /* Make peer's address string. */
871 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000872 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000873
874 /* Set up peer's events and timers. */
875 if (! active && peer_active (peer))
876 bgp_timer_set (peer);
877
878 return peer;
879}
880
pauleb821182004-05-01 08:44:08 +0000881/* Make accept BGP peer. Called from bgp_accept (). */
882struct peer *
883peer_create_accept (struct bgp *bgp)
884{
885 struct peer *peer;
886
Paul Jakma6f585442006-10-22 19:13:07 +0000887 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000888
889 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000890 listnode_add_sort (bgp->peer, peer);
891
892 return peer;
893}
894
paul718e3742002-12-13 20:15:29 +0000895/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000896static void
paul718e3742002-12-13 20:15:29 +0000897peer_as_change (struct peer *peer, as_t as)
898{
899 int type;
900
901 /* Stop peer. */
902 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
903 {
904 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000905 {
906 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
907 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
908 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
909 }
paul718e3742002-12-13 20:15:29 +0000910 else
911 BGP_EVENT_ADD (peer, BGP_Stop);
912 }
913 type = peer_sort (peer);
914 peer->as = as;
915
paul848973c2003-08-13 00:32:49 +0000916 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
917 && ! bgp_confederation_peers_check (peer->bgp, as)
918 && peer->bgp->as != as)
919 peer->local_as = peer->bgp->confed_id;
920 else
921 peer->local_as = peer->bgp->as;
922
paul718e3742002-12-13 20:15:29 +0000923 /* Advertisement-interval reset */
924 if (peer_sort (peer) == BGP_PEER_IBGP)
925 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
926 else
927 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
928
929 /* TTL reset */
930 if (peer_sort (peer) == BGP_PEER_IBGP)
931 peer->ttl = 255;
932 else if (type == BGP_PEER_IBGP)
933 peer->ttl = 1;
934
935 /* reflector-client reset */
936 if (peer_sort (peer) != BGP_PEER_IBGP)
937 {
938 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
939 PEER_FLAG_REFLECTOR_CLIENT);
940 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
941 PEER_FLAG_REFLECTOR_CLIENT);
942 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
943 PEER_FLAG_REFLECTOR_CLIENT);
944 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
945 PEER_FLAG_REFLECTOR_CLIENT);
946 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
947 PEER_FLAG_REFLECTOR_CLIENT);
948 }
949
950 /* local-as reset */
951 if (peer_sort (peer) != BGP_PEER_EBGP)
952 {
953 peer->change_local_as = 0;
954 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
955 }
956}
957
958/* If peer does not exist, create new one. If peer already exists,
959 set AS number to the peer. */
960int
961peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
962 afi_t afi, safi_t safi)
963{
964 struct peer *peer;
965 as_t local_as;
966
967 peer = peer_lookup (bgp, su);
968
969 if (peer)
970 {
971 /* When this peer is a member of peer-group. */
972 if (peer->group)
973 {
974 if (peer->group->conf->as)
975 {
976 /* Return peer group's AS number. */
977 *as = peer->group->conf->as;
978 return BGP_ERR_PEER_GROUP_MEMBER;
979 }
980 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
981 {
982 if (bgp->as != *as)
983 {
984 *as = peer->as;
985 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
986 }
987 }
988 else
989 {
990 if (bgp->as == *as)
991 {
992 *as = peer->as;
993 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
994 }
995 }
996 }
997
998 /* Existing peer's AS number change. */
999 if (peer->as != *as)
1000 peer_as_change (peer, *as);
1001 }
1002 else
1003 {
1004
1005 /* If the peer is not part of our confederation, and its not an
1006 iBGP peer then spoof the source AS */
1007 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1008 && ! bgp_confederation_peers_check (bgp, *as)
1009 && bgp->as != *as)
1010 local_as = bgp->confed_id;
1011 else
1012 local_as = bgp->as;
1013
1014 /* If this is IPv4 unicast configuration and "no bgp default
1015 ipv4-unicast" is specified. */
1016
1017 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1018 && afi == AFI_IP && safi == SAFI_UNICAST)
1019 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1020 else
1021 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1022 }
1023
1024 return 0;
1025}
1026
1027/* Activate the peer or peer group for specified AFI and SAFI. */
1028int
1029peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1030{
1031 int active;
1032
1033 if (peer->afc[afi][safi])
1034 return 0;
1035
1036 /* Activate the address family configuration. */
1037 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1038 peer->afc[afi][safi] = 1;
1039 else
1040 {
1041 active = peer_active (peer);
1042
1043 peer->afc[afi][safi] = 1;
1044
1045 if (! active && peer_active (peer))
1046 bgp_timer_set (peer);
1047 else
1048 {
1049 if (peer->status == Established)
1050 {
1051 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1052 {
1053 peer->afc_adv[afi][safi] = 1;
1054 bgp_capability_send (peer, afi, safi,
1055 CAPABILITY_CODE_MP,
1056 CAPABILITY_ACTION_SET);
1057 if (peer->afc_recv[afi][safi])
1058 {
1059 peer->afc_nego[afi][safi] = 1;
1060 bgp_announce_route (peer, afi, safi);
1061 }
1062 }
1063 else
hassoe0701b72004-05-20 09:19:34 +00001064 {
1065 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1066 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1067 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1068 }
paul718e3742002-12-13 20:15:29 +00001069 }
1070 }
1071 }
1072 return 0;
1073}
1074
1075int
1076peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1077{
1078 struct peer_group *group;
1079 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001080 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001081
1082 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1083 {
1084 group = peer->group;
1085
paul1eb8ef22005-04-07 07:30:20 +00001086 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001087 {
1088 if (peer1->af_group[afi][safi])
1089 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1090 }
1091 }
1092 else
1093 {
1094 if (peer->af_group[afi][safi])
1095 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1096 }
1097
1098 if (! peer->afc[afi][safi])
1099 return 0;
1100
1101 /* De-activate the address family configuration. */
1102 peer->afc[afi][safi] = 0;
1103 peer_af_flag_reset (peer, afi, safi);
1104
1105 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1106 {
1107 if (peer->status == Established)
1108 {
1109 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1110 {
1111 peer->afc_adv[afi][safi] = 0;
1112 peer->afc_nego[afi][safi] = 0;
1113
1114 if (peer_active_nego (peer))
1115 {
1116 bgp_capability_send (peer, afi, safi,
1117 CAPABILITY_CODE_MP,
1118 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001119 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001120 peer->pcount[afi][safi] = 0;
1121 }
1122 else
hassoe0701b72004-05-20 09:19:34 +00001123 {
1124 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1125 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1126 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1127 }
paul718e3742002-12-13 20:15:29 +00001128 }
1129 else
hassoe0701b72004-05-20 09:19:34 +00001130 {
1131 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1132 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1133 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1134 }
paul718e3742002-12-13 20:15:29 +00001135 }
1136 }
1137 return 0;
1138}
1139
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001140static void
hasso93406d82005-02-02 14:40:33 +00001141peer_nsf_stop (struct peer *peer)
1142{
1143 afi_t afi;
1144 safi_t safi;
1145
1146 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1147 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1148
1149 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001150 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001151 peer->nsf[afi][safi] = 0;
1152
1153 if (peer->t_gr_restart)
1154 {
1155 BGP_TIMER_OFF (peer->t_gr_restart);
1156 if (BGP_DEBUG (events, EVENTS))
1157 zlog_debug ("%s graceful restart timer stopped", peer->host);
1158 }
1159 if (peer->t_gr_stale)
1160 {
1161 BGP_TIMER_OFF (peer->t_gr_stale);
1162 if (BGP_DEBUG (events, EVENTS))
1163 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1164 }
1165 bgp_clear_route_all (peer);
1166}
1167
Paul Jakmaca058a32006-09-14 02:58:49 +00001168/* Delete peer from confguration.
1169 *
1170 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1171 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1172 *
1173 * This function /should/ take care to be idempotent, to guard against
1174 * it being called multiple times through stray events that come in
1175 * that happen to result in this function being called again. That
1176 * said, getting here for a "Deleted" peer is a bug in the neighbour
1177 * FSM.
1178 */
paul718e3742002-12-13 20:15:29 +00001179int
1180peer_delete (struct peer *peer)
1181{
1182 int i;
1183 afi_t afi;
1184 safi_t safi;
1185 struct bgp *bgp;
1186 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001187 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001188
Paul Jakmaca058a32006-09-14 02:58:49 +00001189 assert (peer->status != Deleted);
1190
paul718e3742002-12-13 20:15:29 +00001191 bgp = peer->bgp;
1192
hasso93406d82005-02-02 14:40:33 +00001193 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1194 peer_nsf_stop (peer);
1195
Chris Caputo228da422009-07-18 05:44:03 +00001196 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001197 relationship. */
1198 if (peer->group)
1199 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001200 if ((pn = listnode_lookup (peer->group->peer, peer)))
1201 {
1202 peer = peer_unlock (peer); /* group->peer list reference */
1203 list_delete_node (peer->group->peer, pn);
1204 }
paul718e3742002-12-13 20:15:29 +00001205 peer->group = NULL;
1206 }
paul200df112005-06-01 11:17:05 +00001207
paul718e3742002-12-13 20:15:29 +00001208 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001209 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1210 * executed after peer structure is deleted.
1211 */
hassoe0701b72004-05-20 09:19:34 +00001212 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001213 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001214 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001215
1216 /* Password configuration */
1217 if (peer->password)
1218 {
1219 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1220 peer->password = NULL;
1221
1222 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1223 bgp_md5_set (peer);
1224 }
1225
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001227
paul718e3742002-12-13 20:15:29 +00001228 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001229 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1230 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001231 {
Chris Caputo228da422009-07-18 05:44:03 +00001232 peer_unlock (peer); /* bgp peer list reference */
1233 list_delete_node (bgp->peer, pn);
1234 }
paul200df112005-06-01 11:17:05 +00001235
Chris Caputo228da422009-07-18 05:44:03 +00001236 if (peer_rsclient_active (peer)
1237 && (pn = listnode_lookup (bgp->rsclient, peer)))
1238 {
1239 peer_unlock (peer); /* rsclient list reference */
1240 list_delete_node (bgp->rsclient, pn);
1241
1242 /* Clear our own rsclient ribs. */
1243 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1244 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1245 if (CHECK_FLAG(peer->af_flags[afi][safi],
1246 PEER_FLAG_RSERVER_CLIENT))
1247 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001248 }
1249
1250 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1251 member of a peer_group. */
1252 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1253 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1254 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001255 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001256
paul200df112005-06-01 11:17:05 +00001257 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001258 if (peer->ibuf)
1259 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001260 if (peer->obuf)
1261 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001262 if (peer->work)
1263 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001264 peer->obuf = NULL;
1265 peer->work = peer->ibuf = NULL;
1266
paul718e3742002-12-13 20:15:29 +00001267 /* Local and remote addresses. */
1268 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001269 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001270 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001271 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001272 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001273
paul718e3742002-12-13 20:15:29 +00001274 /* Free filter related memory. */
1275 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1276 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1277 {
1278 filter = &peer->filter[afi][safi];
1279
1280 for (i = FILTER_IN; i < FILTER_MAX; i++)
1281 {
1282 if (filter->dlist[i].name)
1283 free (filter->dlist[i].name);
1284 if (filter->plist[i].name)
1285 free (filter->plist[i].name);
1286 if (filter->aslist[i].name)
1287 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001288
1289 filter->dlist[i].name = NULL;
1290 filter->plist[i].name = NULL;
1291 filter->aslist[i].name = NULL;
1292 }
1293 for (i = RMAP_IN; i < RMAP_MAX; i++)
1294 {
paul718e3742002-12-13 20:15:29 +00001295 if (filter->map[i].name)
1296 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001297 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001298 }
1299
1300 if (filter->usmap.name)
1301 free (filter->usmap.name);
1302
1303 if (peer->default_rmap[afi][safi].name)
1304 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001305
1306 filter->usmap.name = NULL;
1307 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001308 }
paul200df112005-06-01 11:17:05 +00001309
1310 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001311
1312 return 0;
1313}
1314
paul94f2b392005-06-28 12:44:16 +00001315static int
paul718e3742002-12-13 20:15:29 +00001316peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1317{
1318 return strcmp (g1->name, g2->name);
1319}
1320
1321/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001322static int
paul718e3742002-12-13 20:15:29 +00001323peer_group_active (struct peer *peer)
1324{
1325 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1326 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1327 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1328 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1329 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1330 return 1;
1331 return 0;
1332}
1333
1334/* Peer group cofiguration. */
1335static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001336peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001337{
1338 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1339 sizeof (struct peer_group));
1340}
1341
paul94f2b392005-06-28 12:44:16 +00001342static void
paul718e3742002-12-13 20:15:29 +00001343peer_group_free (struct peer_group *group)
1344{
1345 XFREE (MTYPE_PEER_GROUP, group);
1346}
1347
1348struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001349peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001350{
1351 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001352 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001353
paul1eb8ef22005-04-07 07:30:20 +00001354 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001355 {
1356 if (strcmp (group->name, name) == 0)
1357 return group;
1358 }
1359 return NULL;
1360}
1361
1362struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001363peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct peer_group *group;
1366
1367 group = peer_group_lookup (bgp, name);
1368 if (group)
1369 return group;
1370
1371 group = peer_group_new ();
1372 group->bgp = bgp;
1373 group->name = strdup (name);
1374 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001375 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001376 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1377 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001378 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001379 group->conf->group = group;
1380 group->conf->as = 0;
1381 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001382 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001383 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1384 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1385 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1386 group->conf->keepalive = 0;
1387 group->conf->holdtime = 0;
1388 group->conf->connect = 0;
1389 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1390 listnode_add_sort (bgp->group, group);
1391
1392 return 0;
1393}
1394
paul94f2b392005-06-28 12:44:16 +00001395static void
paul718e3742002-12-13 20:15:29 +00001396peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1397 afi_t afi, safi_t safi)
1398{
1399 int in = FILTER_IN;
1400 int out = FILTER_OUT;
1401 struct peer *conf;
1402 struct bgp_filter *pfilter;
1403 struct bgp_filter *gfilter;
1404
1405 conf = group->conf;
1406 pfilter = &peer->filter[afi][safi];
1407 gfilter = &conf->filter[afi][safi];
1408
1409 /* remote-as */
1410 if (conf->as)
1411 peer->as = conf->as;
1412
1413 /* remote-as */
1414 if (conf->change_local_as)
1415 peer->change_local_as = conf->change_local_as;
1416
1417 /* TTL */
1418 peer->ttl = conf->ttl;
1419
Nick Hilliardfa411a22011-03-23 15:33:17 +00001420 /* GTSM hops */
1421 peer->gtsm_hops = conf->gtsm_hops;
1422
paul718e3742002-12-13 20:15:29 +00001423 /* Weight */
1424 peer->weight = conf->weight;
1425
1426 /* peer flags apply */
1427 peer->flags = conf->flags;
1428 /* peer af_flags apply */
1429 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1430 /* peer config apply */
1431 peer->config = conf->config;
1432
1433 /* peer timers apply */
1434 peer->holdtime = conf->holdtime;
1435 peer->keepalive = conf->keepalive;
1436 peer->connect = conf->connect;
1437 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1438 peer->v_connect = conf->connect;
1439 else
1440 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1441
1442 /* advertisement-interval reset */
1443 if (peer_sort (peer) == BGP_PEER_IBGP)
1444 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1445 else
1446 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1447
Paul Jakma0df7c912008-07-21 21:02:49 +00001448 /* password apply */
1449 if (peer->password)
1450 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1451
1452 if (conf->password)
1453 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1454 else
1455 peer->password = NULL;
1456
1457 bgp_md5_set (peer);
1458
paul718e3742002-12-13 20:15:29 +00001459 /* maximum-prefix */
1460 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001461 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001462 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001463
1464 /* allowas-in */
1465 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1466
paulfee0f4c2004-09-13 05:12:46 +00001467 /* route-server-client */
1468 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1469 {
1470 /* Make peer's RIB point to group's RIB. */
1471 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1472
1473 /* Import policy. */
1474 if (pfilter->map[RMAP_IMPORT].name)
1475 free (pfilter->map[RMAP_IMPORT].name);
1476 if (gfilter->map[RMAP_IMPORT].name)
1477 {
1478 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1479 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1480 }
1481 else
1482 {
1483 pfilter->map[RMAP_IMPORT].name = NULL;
1484 pfilter->map[RMAP_IMPORT].map = NULL;
1485 }
1486
1487 /* Export policy. */
1488 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1489 {
1490 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1491 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1492 }
1493 }
1494
paul718e3742002-12-13 20:15:29 +00001495 /* default-originate route-map */
1496 if (conf->default_rmap[afi][safi].name)
1497 {
1498 if (peer->default_rmap[afi][safi].name)
1499 free (peer->default_rmap[afi][safi].name);
1500 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1501 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1502 }
1503
1504 /* update-source apply */
1505 if (conf->update_source)
1506 {
1507 if (peer->update_source)
1508 sockunion_free (peer->update_source);
1509 if (peer->update_if)
1510 {
1511 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1512 peer->update_if = NULL;
1513 }
1514 peer->update_source = sockunion_dup (conf->update_source);
1515 }
1516 else if (conf->update_if)
1517 {
1518 if (peer->update_if)
1519 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1520 if (peer->update_source)
1521 {
1522 sockunion_free (peer->update_source);
1523 peer->update_source = NULL;
1524 }
1525 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1526 }
1527
1528 /* inbound filter apply */
1529 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1530 {
1531 if (pfilter->dlist[in].name)
1532 free (pfilter->dlist[in].name);
1533 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1534 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1535 }
1536 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1537 {
1538 if (pfilter->plist[in].name)
1539 free (pfilter->plist[in].name);
1540 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1541 pfilter->plist[in].plist = gfilter->plist[in].plist;
1542 }
1543 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1544 {
1545 if (pfilter->aslist[in].name)
1546 free (pfilter->aslist[in].name);
1547 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1548 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1549 }
paulfee0f4c2004-09-13 05:12:46 +00001550 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001551 {
paulfee0f4c2004-09-13 05:12:46 +00001552 if (pfilter->map[RMAP_IN].name)
1553 free (pfilter->map[RMAP_IN].name);
1554 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1555 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001556 }
1557
1558 /* outbound filter apply */
1559 if (gfilter->dlist[out].name)
1560 {
1561 if (pfilter->dlist[out].name)
1562 free (pfilter->dlist[out].name);
1563 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1564 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1565 }
1566 else
1567 {
1568 if (pfilter->dlist[out].name)
1569 free (pfilter->dlist[out].name);
1570 pfilter->dlist[out].name = NULL;
1571 pfilter->dlist[out].alist = NULL;
1572 }
1573 if (gfilter->plist[out].name)
1574 {
1575 if (pfilter->plist[out].name)
1576 free (pfilter->plist[out].name);
1577 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1578 pfilter->plist[out].plist = gfilter->plist[out].plist;
1579 }
1580 else
1581 {
1582 if (pfilter->plist[out].name)
1583 free (pfilter->plist[out].name);
1584 pfilter->plist[out].name = NULL;
1585 pfilter->plist[out].plist = NULL;
1586 }
1587 if (gfilter->aslist[out].name)
1588 {
1589 if (pfilter->aslist[out].name)
1590 free (pfilter->aslist[out].name);
1591 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1592 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1593 }
1594 else
1595 {
1596 if (pfilter->aslist[out].name)
1597 free (pfilter->aslist[out].name);
1598 pfilter->aslist[out].name = NULL;
1599 pfilter->aslist[out].aslist = NULL;
1600 }
paulfee0f4c2004-09-13 05:12:46 +00001601 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001602 {
paulfee0f4c2004-09-13 05:12:46 +00001603 if (pfilter->map[RMAP_OUT].name)
1604 free (pfilter->map[RMAP_OUT].name);
1605 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1606 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001607 }
1608 else
1609 {
paulfee0f4c2004-09-13 05:12:46 +00001610 if (pfilter->map[RMAP_OUT].name)
1611 free (pfilter->map[RMAP_OUT].name);
1612 pfilter->map[RMAP_OUT].name = NULL;
1613 pfilter->map[RMAP_OUT].map = NULL;
1614 }
1615
1616 /* RS-client's import/export route-maps. */
1617 if (gfilter->map[RMAP_IMPORT].name)
1618 {
1619 if (pfilter->map[RMAP_IMPORT].name)
1620 free (pfilter->map[RMAP_IMPORT].name);
1621 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1622 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1623 }
1624 else
1625 {
1626 if (pfilter->map[RMAP_IMPORT].name)
1627 free (pfilter->map[RMAP_IMPORT].name);
1628 pfilter->map[RMAP_IMPORT].name = NULL;
1629 pfilter->map[RMAP_IMPORT].map = NULL;
1630 }
1631 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1632 {
1633 if (pfilter->map[RMAP_EXPORT].name)
1634 free (pfilter->map[RMAP_EXPORT].name);
1635 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1636 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001637 }
1638
1639 if (gfilter->usmap.name)
1640 {
1641 if (pfilter->usmap.name)
1642 free (pfilter->usmap.name);
1643 pfilter->usmap.name = strdup (gfilter->usmap.name);
1644 pfilter->usmap.map = gfilter->usmap.map;
1645 }
1646 else
1647 {
1648 if (pfilter->usmap.name)
1649 free (pfilter->usmap.name);
1650 pfilter->usmap.name = NULL;
1651 pfilter->usmap.map = NULL;
1652 }
1653}
1654
1655/* Peer group's remote AS configuration. */
1656int
paulfd79ac92004-10-13 05:06:08 +00001657peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001658{
1659 struct peer_group *group;
1660 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001661 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001662
1663 group = peer_group_lookup (bgp, group_name);
1664 if (! group)
1665 return -1;
1666
1667 if (group->conf->as == *as)
1668 return 0;
1669
1670 /* When we setup peer-group AS number all peer group member's AS
1671 number must be updated to same number. */
1672 peer_as_change (group->conf, *as);
1673
paul1eb8ef22005-04-07 07:30:20 +00001674 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001675 {
1676 if (peer->as != *as)
1677 peer_as_change (peer, *as);
1678 }
1679
1680 return 0;
1681}
1682
1683int
1684peer_group_delete (struct peer_group *group)
1685{
1686 struct bgp *bgp;
1687 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001688 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001689
1690 bgp = group->bgp;
1691
paul1eb8ef22005-04-07 07:30:20 +00001692 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001693 {
1694 peer->group = NULL;
1695 peer_delete (peer);
1696 }
1697 list_delete (group->peer);
1698
1699 free (group->name);
1700 group->name = NULL;
1701
1702 group->conf->group = NULL;
1703 peer_delete (group->conf);
1704
1705 /* Delete from all peer_group list. */
1706 listnode_delete (bgp->group, group);
1707
1708 peer_group_free (group);
1709
1710 return 0;
1711}
1712
1713int
1714peer_group_remote_as_delete (struct peer_group *group)
1715{
1716 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001717 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001718
1719 if (! group->conf->as)
1720 return 0;
1721
paul1eb8ef22005-04-07 07:30:20 +00001722 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001723 {
1724 peer->group = NULL;
1725 peer_delete (peer);
1726 }
1727 list_delete_all_node (group->peer);
1728
1729 group->conf->as = 0;
1730
1731 return 0;
1732}
1733
1734/* Bind specified peer to peer group. */
1735int
1736peer_group_bind (struct bgp *bgp, union sockunion *su,
1737 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1738{
1739 struct peer *peer;
1740 int first_member = 0;
1741
1742 /* Check peer group's address family. */
1743 if (! group->conf->afc[afi][safi])
1744 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1745
1746 /* Lookup the peer. */
1747 peer = peer_lookup (bgp, su);
1748
1749 /* Create a new peer. */
1750 if (! peer)
1751 {
1752 if (! group->conf->as)
1753 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1754
1755 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1756 peer->group = group;
1757 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001758
Paul Jakmaca058a32006-09-14 02:58:49 +00001759 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001760 listnode_add (group->peer, peer);
1761 peer_group2peer_config_copy (group, peer, afi, safi);
1762
1763 return 0;
1764 }
1765
1766 /* When the peer already belongs to peer group, check the consistency. */
1767 if (peer->af_group[afi][safi])
1768 {
1769 if (strcmp (peer->group->name, group->name) != 0)
1770 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1771
1772 return 0;
1773 }
1774
1775 /* Check current peer group configuration. */
1776 if (peer_group_active (peer)
1777 && strcmp (peer->group->name, group->name) != 0)
1778 return BGP_ERR_PEER_GROUP_MISMATCH;
1779
1780 if (! group->conf->as)
1781 {
1782 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1783 && peer_sort (group->conf) != peer_sort (peer))
1784 {
1785 if (as)
1786 *as = peer->as;
1787 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1788 }
1789
1790 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1791 first_member = 1;
1792 }
1793
1794 peer->af_group[afi][safi] = 1;
1795 peer->afc[afi][safi] = 1;
1796 if (! peer->group)
1797 {
1798 peer->group = group;
paul200df112005-06-01 11:17:05 +00001799
Paul Jakmaca058a32006-09-14 02:58:49 +00001800 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001801 listnode_add (group->peer, peer);
1802 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001803 else
1804 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001805
1806 if (first_member)
1807 {
1808 /* Advertisement-interval reset */
1809 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1810 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1811 else
1812 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1813
1814 /* ebgp-multihop reset */
1815 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1816 group->conf->ttl = 255;
1817
1818 /* local-as reset */
1819 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1820 {
1821 group->conf->change_local_as = 0;
1822 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1823 }
1824 }
paulfee0f4c2004-09-13 05:12:46 +00001825
1826 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1827 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001828 struct listnode *pn;
1829
paulfee0f4c2004-09-13 05:12:46 +00001830 /* If it's not configured as RSERVER_CLIENT in any other address
1831 family, without being member of a peer_group, remove it from
1832 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001833 if (! peer_rsclient_active (peer)
1834 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001835 {
1836 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001837 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001838
1839 /* Clear our own rsclient rib for this afi/safi. */
1840 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001841 }
paulfee0f4c2004-09-13 05:12:46 +00001842
Paul Jakmab608d5b2008-07-02 02:12:07 +00001843 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001844
1845 /* Import policy. */
1846 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1847 {
1848 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1849 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1850 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1851 }
1852
1853 /* Export policy. */
1854 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1855 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1856 {
1857 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1858 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1859 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1860 }
1861 }
1862
paul718e3742002-12-13 20:15:29 +00001863 peer_group2peer_config_copy (group, peer, afi, safi);
1864
1865 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001866 {
1867 peer->last_reset = PEER_DOWN_RMAP_BIND;
1868 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1869 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1870 }
paul718e3742002-12-13 20:15:29 +00001871 else
1872 BGP_EVENT_ADD (peer, BGP_Stop);
1873
1874 return 0;
1875}
1876
1877int
1878peer_group_unbind (struct bgp *bgp, struct peer *peer,
1879 struct peer_group *group, afi_t afi, safi_t safi)
1880{
1881 if (! peer->af_group[afi][safi])
1882 return 0;
1883
1884 if (group != peer->group)
1885 return BGP_ERR_PEER_GROUP_MISMATCH;
1886
1887 peer->af_group[afi][safi] = 0;
1888 peer->afc[afi][safi] = 0;
1889 peer_af_flag_reset (peer, afi, safi);
1890
paulfee0f4c2004-09-13 05:12:46 +00001891 if (peer->rib[afi][safi])
1892 peer->rib[afi][safi] = NULL;
1893
paul718e3742002-12-13 20:15:29 +00001894 if (! peer_group_active (peer))
1895 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001896 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001897 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001898 listnode_delete (group->peer, peer);
1899 peer->group = NULL;
1900 if (group->conf->as)
1901 {
1902 peer_delete (peer);
1903 return 0;
1904 }
1905 peer_global_config_reset (peer);
1906 }
1907
1908 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001909 {
1910 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1911 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1912 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1913 }
paul718e3742002-12-13 20:15:29 +00001914 else
1915 BGP_EVENT_ADD (peer, BGP_Stop);
1916
1917 return 0;
1918}
1919
1920/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001921static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001922bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001923{
1924 struct bgp *bgp;
1925 afi_t afi;
1926 safi_t safi;
1927
paul200df112005-06-01 11:17:05 +00001928 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1929 return NULL;
1930
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001931 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001932 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001933 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001934
1935 bgp->peer = list_new ();
1936 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1937
1938 bgp->group = list_new ();
1939 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1940
paulfee0f4c2004-09-13 05:12:46 +00001941 bgp->rsclient = list_new ();
1942 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1943
paul718e3742002-12-13 20:15:29 +00001944 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1945 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1946 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001947 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1948 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1949 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001950 }
1951
1952 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1953 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1954 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001955 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1956 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001957
1958 bgp->as = *as;
1959
1960 if (name)
1961 bgp->name = strdup (name);
1962
1963 return bgp;
1964}
1965
1966/* Return first entry of BGP. */
1967struct bgp *
paul94f2b392005-06-28 12:44:16 +00001968bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001969{
1970 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001971 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001972 return NULL;
1973}
1974
1975/* Lookup BGP entry. */
1976struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001977bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001978{
1979 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001980 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001981
paul1eb8ef22005-04-07 07:30:20 +00001982 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001983 if (bgp->as == as
1984 && ((bgp->name == NULL && name == NULL)
1985 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1986 return bgp;
1987 return NULL;
1988}
1989
1990/* Lookup BGP structure by view name. */
1991struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001992bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001993{
1994 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001995 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001996
paul1eb8ef22005-04-07 07:30:20 +00001997 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001998 if ((bgp->name == NULL && name == NULL)
1999 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2000 return bgp;
2001 return NULL;
2002}
2003
2004/* Called from VTY commands. */
2005int
paulfd79ac92004-10-13 05:06:08 +00002006bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002007{
2008 struct bgp *bgp;
2009
2010 /* Multiple instance check. */
2011 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2012 {
2013 if (name)
2014 bgp = bgp_lookup_by_name (name);
2015 else
2016 bgp = bgp_get_default ();
2017
2018 /* Already exists. */
2019 if (bgp)
2020 {
2021 if (bgp->as != *as)
2022 {
2023 *as = bgp->as;
2024 return BGP_ERR_INSTANCE_MISMATCH;
2025 }
2026 *bgp_val = bgp;
2027 return 0;
2028 }
2029 }
2030 else
2031 {
2032 /* BGP instance name can not be specified for single instance. */
2033 if (name)
2034 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2035
2036 /* Get default BGP structure if exists. */
2037 bgp = bgp_get_default ();
2038
2039 if (bgp)
2040 {
2041 if (bgp->as != *as)
2042 {
2043 *as = bgp->as;
2044 return BGP_ERR_AS_MISMATCH;
2045 }
2046 *bgp_val = bgp;
2047 return 0;
2048 }
2049 }
2050
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002051 /* Create BGP server socket, if first instance. */
2052 if (list_isempty(bm->bgp))
2053 {
2054 if (bgp_socket (bm->port, bm->address) < 0)
2055 return BGP_ERR_INVALID_VALUE;
2056 }
2057
paul718e3742002-12-13 20:15:29 +00002058 bgp = bgp_create (as, name);
2059 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002060 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002061 *bgp_val = bgp;
2062
2063 return 0;
2064}
2065
2066/* Delete BGP instance. */
2067int
2068bgp_delete (struct bgp *bgp)
2069{
2070 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002071 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002072 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002073 struct listnode *next;
2074 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002075 int i;
2076
2077 /* Delete static route. */
2078 bgp_static_delete (bgp);
2079
2080 /* Unset redistribution. */
2081 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2082 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2083 if (i != ZEBRA_ROUTE_BGP)
2084 bgp_redistribute_unset (bgp, afi, i);
2085
paul1eb8ef22005-04-07 07:30:20 +00002086 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2087 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002088
Chris Caputo228da422009-07-18 05:44:03 +00002089 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2090 peer_group_delete (group);
2091
2092 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002093
2094 if (bgp->peer_self) {
2095 peer_delete(bgp->peer_self);
2096 bgp->peer_self = NULL;
2097 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002098
2099 /* Remove visibility via the master list - there may however still be
2100 * routes to be processed still referencing the struct bgp.
2101 */
2102 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002103 if (list_isempty(bm->bgp))
2104 bgp_close ();
2105
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002106 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002107
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002108 return 0;
2109}
2110
2111static void bgp_free (struct bgp *);
2112
2113void
2114bgp_lock (struct bgp *bgp)
2115{
2116 ++bgp->lock;
2117}
2118
2119void
2120bgp_unlock(struct bgp *bgp)
2121{
Chris Caputo228da422009-07-18 05:44:03 +00002122 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002123 if (--bgp->lock == 0)
2124 bgp_free (bgp);
2125}
2126
2127static void
2128bgp_free (struct bgp *bgp)
2129{
2130 afi_t afi;
2131 safi_t safi;
2132
2133 list_delete (bgp->group);
2134 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002135 list_delete (bgp->rsclient);
2136
paul718e3742002-12-13 20:15:29 +00002137 if (bgp->name)
2138 free (bgp->name);
2139
2140 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2141 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2142 {
2143 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002144 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002145 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002146 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002147 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002148 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002149 }
2150 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002151}
2152
2153struct peer *
2154peer_lookup (struct bgp *bgp, union sockunion *su)
2155{
2156 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002157 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002158
Steve Hillfc4dc592009-07-28 17:54:35 +01002159 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002160 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002161 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2162 if (sockunion_same (&peer->su, su)
2163 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2164 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002165 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002166 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002167 {
2168 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002169
Paul Jakma2158ad22009-07-28 18:10:55 +01002170 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2171 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2172 if (sockunion_same (&peer->su, su)
2173 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2174 return peer;
paul718e3742002-12-13 20:15:29 +00002175 }
2176 return NULL;
2177}
2178
2179struct peer *
2180peer_lookup_with_open (union sockunion *su, as_t remote_as,
2181 struct in_addr *remote_id, int *as)
2182{
2183 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002184 struct listnode *node;
2185 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002186 struct bgp *bgp;
2187
Steve Hillfc4dc592009-07-28 17:54:35 +01002188 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002189 return NULL;
2190
Paul Jakma9d878772009-08-05 16:25:16 +01002191 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002192 {
Paul Jakma9d878772009-08-05 16:25:16 +01002193 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2194 {
2195 if (sockunion_same (&peer->su, su)
2196 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2197 {
2198 if (peer->as == remote_as
2199 && peer->remote_id.s_addr == remote_id->s_addr)
2200 return peer;
2201 if (peer->as == remote_as)
2202 *as = 1;
2203 }
2204 }
2205
2206 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2207 {
2208 if (sockunion_same (&peer->su, su)
2209 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2210 {
2211 if (peer->as == remote_as
2212 && peer->remote_id.s_addr == 0)
2213 return peer;
2214 if (peer->as == remote_as)
2215 *as = 1;
2216 }
2217 }
paul718e3742002-12-13 20:15:29 +00002218 }
2219 return NULL;
2220}
2221
2222/* If peer is configured at least one address family return 1. */
2223int
2224peer_active (struct peer *peer)
2225{
2226 if (peer->afc[AFI_IP][SAFI_UNICAST]
2227 || peer->afc[AFI_IP][SAFI_MULTICAST]
2228 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2229 || peer->afc[AFI_IP6][SAFI_UNICAST]
2230 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2231 return 1;
2232 return 0;
2233}
2234
2235/* If peer is negotiated at least one address family return 1. */
2236int
2237peer_active_nego (struct peer *peer)
2238{
2239 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2240 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2241 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2242 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2243 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2244 return 1;
2245 return 0;
2246}
2247
2248/* peer_flag_change_type. */
2249enum peer_change_type
2250{
2251 peer_change_none,
2252 peer_change_reset,
2253 peer_change_reset_in,
2254 peer_change_reset_out,
2255};
2256
paul94f2b392005-06-28 12:44:16 +00002257static void
paul718e3742002-12-13 20:15:29 +00002258peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2259 enum peer_change_type type)
2260{
2261 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2262 return;
2263
2264 if (type == peer_change_reset)
2265 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2266 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2267 else if (type == peer_change_reset_in)
2268 {
2269 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2270 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2271 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2272 else
2273 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2274 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2275 }
2276 else if (type == peer_change_reset_out)
2277 bgp_announce_route (peer, afi, safi);
2278}
2279
2280struct peer_flag_action
2281{
2282 /* Peer's flag. */
2283 u_int32_t flag;
2284
2285 /* This flag can be set for peer-group member. */
2286 u_char not_for_member;
2287
2288 /* Action when the flag is changed. */
2289 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002290
2291 /* Peer down cause */
2292 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002293};
2294
Stephen Hemminger03621952009-07-21 16:27:20 -07002295static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002296 {
2297 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2298 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2299 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2300 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2301 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002302 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002303 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002304 { 0, 0, 0 }
2305 };
2306
Stephen Hemminger03621952009-07-21 16:27:20 -07002307static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002308 {
2309 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2310 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2311 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2312 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2313 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2314 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2315 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2316 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2317 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2318 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2319 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2320 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2321 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002322 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002323 { 0, 0, 0 }
2324 };
2325
2326/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002327static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002328peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002329 struct peer_flag_action *action, u_int32_t flag)
2330{
2331 int i;
2332 int found = 0;
2333 int reset_in = 0;
2334 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002335 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002336
2337 /* Check peer's frag action. */
2338 for (i = 0; i < size; i++)
2339 {
2340 match = &action_list[i];
2341
2342 if (match->flag == 0)
2343 break;
2344
2345 if (match->flag & flag)
2346 {
2347 found = 1;
2348
2349 if (match->type == peer_change_reset_in)
2350 reset_in = 1;
2351 if (match->type == peer_change_reset_out)
2352 reset_out = 1;
2353 if (match->type == peer_change_reset)
2354 {
2355 reset_in = 1;
2356 reset_out = 1;
2357 }
2358 if (match->not_for_member)
2359 action->not_for_member = 1;
2360 }
2361 }
2362
2363 /* Set peer clear type. */
2364 if (reset_in && reset_out)
2365 action->type = peer_change_reset;
2366 else if (reset_in)
2367 action->type = peer_change_reset_in;
2368 else if (reset_out)
2369 action->type = peer_change_reset_out;
2370 else
2371 action->type = peer_change_none;
2372
2373 return found;
2374}
2375
paul94f2b392005-06-28 12:44:16 +00002376static void
paul718e3742002-12-13 20:15:29 +00002377peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2378{
2379 if (flag == PEER_FLAG_SHUTDOWN)
2380 {
2381 if (CHECK_FLAG (peer->flags, flag))
2382 {
hasso93406d82005-02-02 14:40:33 +00002383 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2384 peer_nsf_stop (peer);
2385
hasso0a486e52005-02-01 20:57:17 +00002386 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2387 if (peer->t_pmax_restart)
2388 {
2389 BGP_TIMER_OFF (peer->t_pmax_restart);
2390 if (BGP_DEBUG (events, EVENTS))
2391 zlog_debug ("%s Maximum-prefix restart timer canceled",
2392 peer->host);
2393 }
2394
hasso93406d82005-02-02 14:40:33 +00002395 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2396 peer_nsf_stop (peer);
2397
paul718e3742002-12-13 20:15:29 +00002398 if (peer->status == Established)
2399 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2400 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2401 else
2402 BGP_EVENT_ADD (peer, BGP_Stop);
2403 }
2404 else
2405 {
2406 peer->v_start = BGP_INIT_START_TIMER;
2407 BGP_EVENT_ADD (peer, BGP_Stop);
2408 }
2409 }
2410 else if (peer->status == Established)
2411 {
hassoc9502432005-02-01 22:01:48 +00002412 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2413 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2414 else if (flag == PEER_FLAG_PASSIVE)
2415 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002416 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002417 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002418
hassoc9502432005-02-01 22:01:48 +00002419 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2420 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002421 }
2422 else
2423 BGP_EVENT_ADD (peer, BGP_Stop);
2424}
2425
2426/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002427static int
paul718e3742002-12-13 20:15:29 +00002428peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2429{
2430 int found;
2431 int size;
2432 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002433 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002434 struct peer_flag_action action;
2435
2436 memset (&action, 0, sizeof (struct peer_flag_action));
2437 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2438
2439 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2440
2441 /* No flag action is found. */
2442 if (! found)
2443 return BGP_ERR_INVALID_FLAG;
2444
2445 /* Not for peer-group member. */
2446 if (action.not_for_member && peer_group_active (peer))
2447 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2448
2449 /* When unset the peer-group member's flag we have to check
2450 peer-group configuration. */
2451 if (! set && peer_group_active (peer))
2452 if (CHECK_FLAG (peer->group->conf->flags, flag))
2453 {
2454 if (flag == PEER_FLAG_SHUTDOWN)
2455 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2456 else
2457 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2458 }
2459
2460 /* Flag conflict check. */
2461 if (set
2462 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2463 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2464 return BGP_ERR_PEER_FLAG_CONFLICT;
2465
2466 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2467 {
2468 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2469 return 0;
2470 if (! set && ! CHECK_FLAG (peer->flags, flag))
2471 return 0;
2472 }
2473
2474 if (set)
2475 SET_FLAG (peer->flags, flag);
2476 else
2477 UNSET_FLAG (peer->flags, flag);
2478
2479 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2480 {
2481 if (action.type == peer_change_reset)
2482 peer_flag_modify_action (peer, flag);
2483
2484 return 0;
2485 }
2486
2487 /* peer-group member updates. */
2488 group = peer->group;
2489
paul1eb8ef22005-04-07 07:30:20 +00002490 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002491 {
2492 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2493 continue;
2494
2495 if (! set && ! CHECK_FLAG (peer->flags, flag))
2496 continue;
2497
2498 if (set)
2499 SET_FLAG (peer->flags, flag);
2500 else
2501 UNSET_FLAG (peer->flags, flag);
2502
2503 if (action.type == peer_change_reset)
2504 peer_flag_modify_action (peer, flag);
2505 }
2506 return 0;
2507}
2508
2509int
2510peer_flag_set (struct peer *peer, u_int32_t flag)
2511{
2512 return peer_flag_modify (peer, flag, 1);
2513}
2514
2515int
2516peer_flag_unset (struct peer *peer, u_int32_t flag)
2517{
2518 return peer_flag_modify (peer, flag, 0);
2519}
2520
paul94f2b392005-06-28 12:44:16 +00002521static int
paul718e3742002-12-13 20:15:29 +00002522peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2523{
2524 if (peer->af_group[afi][safi])
2525 return 1;
2526 return 0;
2527}
2528
paul94f2b392005-06-28 12:44:16 +00002529static int
paul718e3742002-12-13 20:15:29 +00002530peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2531 int set)
2532{
2533 int found;
2534 int size;
paul1eb8ef22005-04-07 07:30:20 +00002535 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002536 struct peer_group *group;
2537 struct peer_flag_action action;
2538
2539 memset (&action, 0, sizeof (struct peer_flag_action));
2540 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2541
2542 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2543
2544 /* No flag action is found. */
2545 if (! found)
2546 return BGP_ERR_INVALID_FLAG;
2547
2548 /* Adress family must be activated. */
2549 if (! peer->afc[afi][safi])
2550 return BGP_ERR_PEER_INACTIVE;
2551
2552 /* Not for peer-group member. */
2553 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2554 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2555
2556 /* Spcecial check for reflector client. */
2557 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2558 && peer_sort (peer) != BGP_PEER_IBGP)
2559 return BGP_ERR_NOT_INTERNAL_PEER;
2560
2561 /* Spcecial check for remove-private-AS. */
2562 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2563 && peer_sort (peer) == BGP_PEER_IBGP)
2564 return BGP_ERR_REMOVE_PRIVATE_AS;
2565
2566 /* When unset the peer-group member's flag we have to check
2567 peer-group configuration. */
2568 if (! set && peer->af_group[afi][safi])
2569 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2570 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2571
2572 /* When current flag configuration is same as requested one. */
2573 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2574 {
2575 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2576 return 0;
2577 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2578 return 0;
2579 }
2580
2581 if (set)
2582 SET_FLAG (peer->af_flags[afi][safi], flag);
2583 else
2584 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2585
2586 /* Execute action when peer is established. */
2587 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2588 && peer->status == Established)
2589 {
2590 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2591 bgp_clear_adj_in (peer, afi, safi);
2592 else
hassoe0701b72004-05-20 09:19:34 +00002593 {
2594 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2595 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2596 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2597 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2598 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2599 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2600 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2601 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2602
2603 peer_change_action (peer, afi, safi, action.type);
2604 }
2605
paul718e3742002-12-13 20:15:29 +00002606 }
2607
2608 /* Peer group member updates. */
2609 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2610 {
2611 group = peer->group;
2612
paul1eb8ef22005-04-07 07:30:20 +00002613 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002614 {
2615 if (! peer->af_group[afi][safi])
2616 continue;
2617
2618 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2619 continue;
2620
2621 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2622 continue;
2623
2624 if (set)
2625 SET_FLAG (peer->af_flags[afi][safi], flag);
2626 else
2627 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2628
2629 if (peer->status == Established)
2630 {
2631 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2632 bgp_clear_adj_in (peer, afi, safi);
2633 else
hassoe0701b72004-05-20 09:19:34 +00002634 {
2635 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2636 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2637 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2638 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2639 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2640 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2641 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2642 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2643
2644 peer_change_action (peer, afi, safi, action.type);
2645 }
paul718e3742002-12-13 20:15:29 +00002646 }
2647 }
2648 }
2649 return 0;
2650}
2651
2652int
2653peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2654{
2655 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2656}
2657
2658int
2659peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2660{
2661 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2662}
2663
2664/* EBGP multihop configuration. */
2665int
2666peer_ebgp_multihop_set (struct peer *peer, int ttl)
2667{
2668 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002669 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002670 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002671
2672 if (peer_sort (peer) == BGP_PEER_IBGP)
2673 return 0;
2674
Nick Hilliardfa411a22011-03-23 15:33:17 +00002675 /* see comment in peer_ttl_security_hops_set() */
2676 if (ttl != MAXTTL)
2677 {
2678 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2679 {
2680 group = peer->group;
2681 if (group->conf->gtsm_hops != 0)
2682 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2683
2684 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2685 {
2686 if (peer_sort (peer1) == BGP_PEER_IBGP)
2687 continue;
2688
2689 if (peer1->gtsm_hops != 0)
2690 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2691 }
2692 }
2693 else
2694 {
2695 if (peer->gtsm_hops != 0)
2696 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2697 }
2698 }
2699
paul718e3742002-12-13 20:15:29 +00002700 peer->ttl = ttl;
2701
2702 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2703 {
pauleb821182004-05-01 08:44:08 +00002704 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2705 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002706 }
2707 else
2708 {
2709 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002711 {
2712 if (peer_sort (peer) == BGP_PEER_IBGP)
2713 continue;
paul718e3742002-12-13 20:15:29 +00002714
pauleb821182004-05-01 08:44:08 +00002715 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002716
pauleb821182004-05-01 08:44:08 +00002717 if (peer->fd >= 0)
2718 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2719 }
paul718e3742002-12-13 20:15:29 +00002720 }
2721 return 0;
2722}
2723
2724int
2725peer_ebgp_multihop_unset (struct peer *peer)
2726{
2727 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002728 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002729
2730 if (peer_sort (peer) == BGP_PEER_IBGP)
2731 return 0;
2732
Nick Hilliardfa411a22011-03-23 15:33:17 +00002733 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2734 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2735
paul718e3742002-12-13 20:15:29 +00002736 if (peer_group_active (peer))
2737 peer->ttl = peer->group->conf->ttl;
2738 else
2739 peer->ttl = 1;
2740
2741 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2742 {
pauleb821182004-05-01 08:44:08 +00002743 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2744 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002745 }
2746 else
2747 {
2748 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002749 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002750 {
2751 if (peer_sort (peer) == BGP_PEER_IBGP)
2752 continue;
paul718e3742002-12-13 20:15:29 +00002753
pauleb821182004-05-01 08:44:08 +00002754 peer->ttl = 1;
2755
2756 if (peer->fd >= 0)
2757 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2758 }
paul718e3742002-12-13 20:15:29 +00002759 }
2760 return 0;
2761}
2762
2763/* Neighbor description. */
2764int
2765peer_description_set (struct peer *peer, char *desc)
2766{
2767 if (peer->desc)
2768 XFREE (MTYPE_PEER_DESC, peer->desc);
2769
2770 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2771
2772 return 0;
2773}
2774
2775int
2776peer_description_unset (struct peer *peer)
2777{
2778 if (peer->desc)
2779 XFREE (MTYPE_PEER_DESC, peer->desc);
2780
2781 peer->desc = NULL;
2782
2783 return 0;
2784}
2785
2786/* Neighbor update-source. */
2787int
paulfd79ac92004-10-13 05:06:08 +00002788peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002789{
2790 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002791 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002792
2793 if (peer->update_if)
2794 {
2795 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2796 && strcmp (peer->update_if, ifname) == 0)
2797 return 0;
2798
2799 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2800 peer->update_if = NULL;
2801 }
2802
2803 if (peer->update_source)
2804 {
2805 sockunion_free (peer->update_source);
2806 peer->update_source = NULL;
2807 }
2808
2809 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2810
2811 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2812 {
2813 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002814 {
2815 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2816 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2817 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2818 }
paul718e3742002-12-13 20:15:29 +00002819 else
2820 BGP_EVENT_ADD (peer, BGP_Stop);
2821 return 0;
2822 }
2823
2824 /* peer-group member updates. */
2825 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002826 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002827 {
2828 if (peer->update_if)
2829 {
2830 if (strcmp (peer->update_if, ifname) == 0)
2831 continue;
2832
2833 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2834 peer->update_if = NULL;
2835 }
2836
2837 if (peer->update_source)
2838 {
2839 sockunion_free (peer->update_source);
2840 peer->update_source = NULL;
2841 }
2842
2843 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2844
2845 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002846 {
2847 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2848 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2849 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2850 }
paul718e3742002-12-13 20:15:29 +00002851 else
2852 BGP_EVENT_ADD (peer, BGP_Stop);
2853 }
2854 return 0;
2855}
2856
2857int
2858peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2859{
2860 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002861 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002862
2863 if (peer->update_source)
2864 {
2865 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2866 && sockunion_cmp (peer->update_source, su) == 0)
2867 return 0;
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 (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2881 {
2882 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002883 {
2884 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2885 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2886 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2887 }
paul718e3742002-12-13 20:15:29 +00002888 else
2889 BGP_EVENT_ADD (peer, BGP_Stop);
2890 return 0;
2891 }
2892
2893 /* peer-group member updates. */
2894 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002895 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002896 {
2897 if (peer->update_source)
2898 {
2899 if (sockunion_cmp (peer->update_source, su) == 0)
2900 continue;
2901 sockunion_free (peer->update_source);
2902 peer->update_source = NULL;
2903 }
2904
2905 if (peer->update_if)
2906 {
2907 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2908 peer->update_if = NULL;
2909 }
2910
2911 peer->update_source = sockunion_dup (su);
2912
2913 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002914 {
2915 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2916 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2917 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2918 }
paul718e3742002-12-13 20:15:29 +00002919 else
2920 BGP_EVENT_ADD (peer, BGP_Stop);
2921 }
2922 return 0;
2923}
2924
2925int
2926peer_update_source_unset (struct peer *peer)
2927{
2928 union sockunion *su;
2929 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002930 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002931
2932 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2933 && ! peer->update_source
2934 && ! peer->update_if)
2935 return 0;
2936
2937 if (peer->update_source)
2938 {
2939 sockunion_free (peer->update_source);
2940 peer->update_source = NULL;
2941 }
2942 if (peer->update_if)
2943 {
2944 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2945 peer->update_if = NULL;
2946 }
2947
2948 if (peer_group_active (peer))
2949 {
2950 group = peer->group;
2951
2952 if (group->conf->update_source)
2953 {
2954 su = sockunion_dup (group->conf->update_source);
2955 peer->update_source = su;
2956 }
2957 else if (group->conf->update_if)
2958 peer->update_if =
2959 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2960 }
2961
2962 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2963 {
2964 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002965 {
2966 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2967 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2968 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2969 }
paul718e3742002-12-13 20:15:29 +00002970 else
2971 BGP_EVENT_ADD (peer, BGP_Stop);
2972 return 0;
2973 }
2974
2975 /* peer-group member updates. */
2976 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002977 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002978 {
2979 if (! peer->update_source && ! peer->update_if)
2980 continue;
2981
2982 if (peer->update_source)
2983 {
2984 sockunion_free (peer->update_source);
2985 peer->update_source = NULL;
2986 }
2987
2988 if (peer->update_if)
2989 {
2990 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2991 peer->update_if = NULL;
2992 }
2993
2994 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002995 {
2996 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2997 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2998 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2999 }
paul718e3742002-12-13 20:15:29 +00003000 else
3001 BGP_EVENT_ADD (peer, BGP_Stop);
3002 }
3003 return 0;
3004}
3005
3006int
3007peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003008 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003009{
3010 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003011 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003012
3013 /* Adress family must be activated. */
3014 if (! peer->afc[afi][safi])
3015 return BGP_ERR_PEER_INACTIVE;
3016
3017 /* Default originate can't be used for peer group memeber. */
3018 if (peer_is_group_member (peer, afi, safi))
3019 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3020
3021 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3022 || (rmap && ! peer->default_rmap[afi][safi].name)
3023 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3024 {
3025 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3026
3027 if (rmap)
3028 {
3029 if (peer->default_rmap[afi][safi].name)
3030 free (peer->default_rmap[afi][safi].name);
3031 peer->default_rmap[afi][safi].name = strdup (rmap);
3032 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3033 }
3034 }
3035
3036 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3037 {
3038 if (peer->status == Established && peer->afc_nego[afi][safi])
3039 bgp_default_originate (peer, afi, safi, 0);
3040 return 0;
3041 }
3042
3043 /* peer-group member updates. */
3044 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003045 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003046 {
3047 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3048
3049 if (rmap)
3050 {
3051 if (peer->default_rmap[afi][safi].name)
3052 free (peer->default_rmap[afi][safi].name);
3053 peer->default_rmap[afi][safi].name = strdup (rmap);
3054 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3055 }
3056
3057 if (peer->status == Established && peer->afc_nego[afi][safi])
3058 bgp_default_originate (peer, afi, safi, 0);
3059 }
3060 return 0;
3061}
3062
3063int
3064peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3065{
3066 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003067 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003068
3069 /* Adress family must be activated. */
3070 if (! peer->afc[afi][safi])
3071 return BGP_ERR_PEER_INACTIVE;
3072
3073 /* Default originate can't be used for peer group memeber. */
3074 if (peer_is_group_member (peer, afi, safi))
3075 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3076
3077 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3078 {
3079 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3080
3081 if (peer->default_rmap[afi][safi].name)
3082 free (peer->default_rmap[afi][safi].name);
3083 peer->default_rmap[afi][safi].name = NULL;
3084 peer->default_rmap[afi][safi].map = NULL;
3085 }
3086
3087 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3088 {
3089 if (peer->status == Established && peer->afc_nego[afi][safi])
3090 bgp_default_originate (peer, afi, safi, 1);
3091 return 0;
3092 }
3093
3094 /* peer-group member updates. */
3095 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003096 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003097 {
3098 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3099
3100 if (peer->default_rmap[afi][safi].name)
3101 free (peer->default_rmap[afi][safi].name);
3102 peer->default_rmap[afi][safi].name = NULL;
3103 peer->default_rmap[afi][safi].map = NULL;
3104
3105 if (peer->status == Established && peer->afc_nego[afi][safi])
3106 bgp_default_originate (peer, afi, safi, 1);
3107 }
3108 return 0;
3109}
3110
3111int
3112peer_port_set (struct peer *peer, u_int16_t port)
3113{
3114 peer->port = port;
3115 return 0;
3116}
3117
3118int
3119peer_port_unset (struct peer *peer)
3120{
3121 peer->port = BGP_PORT_DEFAULT;
3122 return 0;
3123}
3124
3125/* neighbor weight. */
3126int
3127peer_weight_set (struct peer *peer, u_int16_t weight)
3128{
3129 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003130 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003131
3132 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3133 peer->weight = weight;
3134
3135 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3136 return 0;
3137
3138 /* peer-group member updates. */
3139 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003140 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003141 {
3142 peer->weight = group->conf->weight;
3143 }
3144 return 0;
3145}
3146
3147int
3148peer_weight_unset (struct peer *peer)
3149{
3150 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003151 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003152
3153 /* Set default weight. */
3154 if (peer_group_active (peer))
3155 peer->weight = peer->group->conf->weight;
3156 else
3157 peer->weight = 0;
3158
3159 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3160
3161 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3162 return 0;
3163
3164 /* peer-group member updates. */
3165 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003166 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003167 {
3168 peer->weight = 0;
3169 }
3170 return 0;
3171}
3172
3173int
3174peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3175{
3176 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003177 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003178
3179 /* Not for peer group memeber. */
3180 if (peer_group_active (peer))
3181 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3182
3183 /* keepalive value check. */
3184 if (keepalive > 65535)
3185 return BGP_ERR_INVALID_VALUE;
3186
3187 /* Holdtime value check. */
3188 if (holdtime > 65535)
3189 return BGP_ERR_INVALID_VALUE;
3190
3191 /* Holdtime value must be either 0 or greater than 3. */
3192 if (holdtime < 3 && holdtime != 0)
3193 return BGP_ERR_INVALID_VALUE;
3194
3195 /* Set value to the configuration. */
3196 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3197 peer->holdtime = holdtime;
3198 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3199
3200 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3201 return 0;
3202
3203 /* peer-group member updates. */
3204 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003205 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003206 {
3207 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3208 peer->holdtime = group->conf->holdtime;
3209 peer->keepalive = group->conf->keepalive;
3210 }
3211 return 0;
3212}
3213
3214int
3215peer_timers_unset (struct peer *peer)
3216{
3217 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003218 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003219
3220 if (peer_group_active (peer))
3221 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3222
3223 /* Clear configuration. */
3224 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3225 peer->keepalive = 0;
3226 peer->holdtime = 0;
3227
3228 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3229 return 0;
3230
3231 /* peer-group member updates. */
3232 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003233 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003234 {
3235 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3236 peer->holdtime = 0;
3237 peer->keepalive = 0;
3238 }
3239
3240 return 0;
3241}
3242
3243int
3244peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3245{
3246 if (peer_group_active (peer))
3247 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3248
3249 if (connect > 65535)
3250 return BGP_ERR_INVALID_VALUE;
3251
3252 /* Set value to the configuration. */
3253 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3254 peer->connect = connect;
3255
3256 /* Set value to timer setting. */
3257 peer->v_connect = connect;
3258
3259 return 0;
3260}
3261
3262int
3263peer_timers_connect_unset (struct peer *peer)
3264{
3265 if (peer_group_active (peer))
3266 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3267
3268 /* Clear configuration. */
3269 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3270 peer->connect = 0;
3271
3272 /* Set timer setting to default value. */
3273 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3274
3275 return 0;
3276}
3277
3278int
3279peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3280{
3281 if (peer_group_active (peer))
3282 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3283
3284 if (routeadv > 600)
3285 return BGP_ERR_INVALID_VALUE;
3286
3287 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3288 peer->routeadv = routeadv;
3289 peer->v_routeadv = routeadv;
3290
3291 return 0;
3292}
3293
3294int
3295peer_advertise_interval_unset (struct peer *peer)
3296{
3297 if (peer_group_active (peer))
3298 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3299
3300 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3301 peer->routeadv = 0;
3302
3303 if (peer_sort (peer) == BGP_PEER_IBGP)
3304 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3305 else
3306 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3307
3308 return 0;
3309}
3310
paul718e3742002-12-13 20:15:29 +00003311/* neighbor interface */
3312int
paulfd79ac92004-10-13 05:06:08 +00003313peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003314{
3315 if (peer->ifname)
3316 free (peer->ifname);
3317 peer->ifname = strdup (str);
3318
3319 return 0;
3320}
3321
3322int
3323peer_interface_unset (struct peer *peer)
3324{
3325 if (peer->ifname)
3326 free (peer->ifname);
3327 peer->ifname = NULL;
3328
3329 return 0;
3330}
3331
3332/* Allow-as in. */
3333int
3334peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
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 (allow_num < 1 || allow_num > 10)
3340 return BGP_ERR_INVALID_VALUE;
3341
3342 if (peer->allowas_in[afi][safi] != allow_num)
3343 {
3344 peer->allowas_in[afi][safi] = allow_num;
3345 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3346 peer_change_action (peer, afi, safi, peer_change_reset_in);
3347 }
3348
3349 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3350 return 0;
3351
3352 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003353 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003354 {
3355 if (peer->allowas_in[afi][safi] != allow_num)
3356 {
3357 peer->allowas_in[afi][safi] = allow_num;
3358 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3359 peer_change_action (peer, afi, safi, peer_change_reset_in);
3360 }
3361
3362 }
3363 return 0;
3364}
3365
3366int
3367peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3368{
3369 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003370 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003371
3372 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3373 {
3374 peer->allowas_in[afi][safi] = 0;
3375 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3376 }
3377
3378 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3379 return 0;
3380
3381 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003382 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003383 {
3384 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3385 {
3386 peer->allowas_in[afi][safi] = 0;
3387 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3388 }
3389 }
3390 return 0;
3391}
3392
3393int
3394peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3395{
3396 struct bgp *bgp = peer->bgp;
3397 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003398 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003399
3400 if (peer_sort (peer) != BGP_PEER_EBGP
3401 && peer_sort (peer) != BGP_PEER_INTERNAL)
3402 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3403
3404 if (bgp->as == as)
3405 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3406
3407 if (peer_group_active (peer))
3408 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3409
3410 if (peer->change_local_as == as &&
3411 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3412 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3413 return 0;
3414
3415 peer->change_local_as = as;
3416 if (no_prepend)
3417 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3418 else
3419 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3420
3421 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3422 {
3423 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003424 {
3425 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3426 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3427 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3428 }
paul718e3742002-12-13 20:15:29 +00003429 else
3430 BGP_EVENT_ADD (peer, BGP_Stop);
3431
3432 return 0;
3433 }
3434
3435 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003436 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003437 {
3438 peer->change_local_as = as;
3439 if (no_prepend)
3440 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3441 else
3442 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3443
3444 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003445 {
3446 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3447 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3448 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3449 }
paul718e3742002-12-13 20:15:29 +00003450 else
3451 BGP_EVENT_ADD (peer, BGP_Stop);
3452 }
3453
3454 return 0;
3455}
3456
3457int
3458peer_local_as_unset (struct peer *peer)
3459{
3460 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003461 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003462
3463 if (peer_group_active (peer))
3464 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3465
3466 if (! peer->change_local_as)
3467 return 0;
3468
3469 peer->change_local_as = 0;
3470 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3471
3472 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3473 {
3474 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003475 {
3476 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3477 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3478 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3479 }
paul718e3742002-12-13 20:15:29 +00003480 else
3481 BGP_EVENT_ADD (peer, BGP_Stop);
3482
3483 return 0;
3484 }
3485
3486 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003488 {
3489 peer->change_local_as = 0;
3490 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3491
3492 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003493 {
3494 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3495 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3496 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3497 }
paul718e3742002-12-13 20:15:29 +00003498 else
3499 BGP_EVENT_ADD (peer, BGP_Stop);
3500 }
3501 return 0;
3502}
3503
Paul Jakma0df7c912008-07-21 21:02:49 +00003504/* Set password for authenticating with the peer. */
3505int
3506peer_password_set (struct peer *peer, const char *password)
3507{
3508 struct listnode *nn, *nnode;
3509 int len = password ? strlen(password) : 0;
3510 int ret = BGP_SUCCESS;
3511
3512 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3513 return BGP_ERR_INVALID_VALUE;
3514
3515 if (peer->password && strcmp (peer->password, password) == 0
3516 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3517 return 0;
3518
3519 if (peer->password)
3520 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3521
3522 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3523
3524 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3525 {
3526 if (peer->status == Established)
3527 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3528 else
3529 BGP_EVENT_ADD (peer, BGP_Stop);
3530
3531 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3532 }
3533
3534 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3535 {
3536 if (peer->password && strcmp (peer->password, password) == 0)
3537 continue;
3538
3539 if (peer->password)
3540 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3541
3542 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3543
3544 if (peer->status == Established)
3545 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3546 else
3547 BGP_EVENT_ADD (peer, BGP_Stop);
3548
3549 if (bgp_md5_set (peer) < 0)
3550 ret = BGP_ERR_TCPSIG_FAILED;
3551 }
3552
3553 return ret;
3554}
3555
3556int
3557peer_password_unset (struct peer *peer)
3558{
3559 struct listnode *nn, *nnode;
3560
3561 if (!peer->password
3562 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3563 return 0;
3564
3565 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3566 {
3567 if (peer_group_active (peer)
3568 && peer->group->conf->password
3569 && strcmp (peer->group->conf->password, peer->password) == 0)
3570 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3571
3572 if (peer->status == Established)
3573 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3574 else
3575 BGP_EVENT_ADD (peer, BGP_Stop);
3576
3577 if (peer->password)
3578 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3579
3580 peer->password = NULL;
3581
3582 bgp_md5_set (peer);
3583
3584 return 0;
3585 }
3586
3587 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3588 peer->password = NULL;
3589
3590 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3591 {
3592 if (!peer->password)
3593 continue;
3594
3595 if (peer->status == Established)
3596 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3597 else
3598 BGP_EVENT_ADD (peer, BGP_Stop);
3599
3600 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3601 peer->password = NULL;
3602
3603 bgp_md5_set (peer);
3604 }
3605
3606 return 0;
3607}
3608
paul718e3742002-12-13 20:15:29 +00003609/* Set distribute list to the peer. */
3610int
3611peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003612 const char *name)
paul718e3742002-12-13 20:15:29 +00003613{
3614 struct bgp_filter *filter;
3615 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003616 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003617
3618 if (! peer->afc[afi][safi])
3619 return BGP_ERR_PEER_INACTIVE;
3620
3621 if (direct != FILTER_IN && direct != FILTER_OUT)
3622 return BGP_ERR_INVALID_VALUE;
3623
3624 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3625 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3626
3627 filter = &peer->filter[afi][safi];
3628
3629 if (filter->plist[direct].name)
3630 return BGP_ERR_PEER_FILTER_CONFLICT;
3631
3632 if (filter->dlist[direct].name)
3633 free (filter->dlist[direct].name);
3634 filter->dlist[direct].name = strdup (name);
3635 filter->dlist[direct].alist = access_list_lookup (afi, name);
3636
3637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3638 return 0;
3639
3640 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003641 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003642 {
3643 filter = &peer->filter[afi][safi];
3644
3645 if (! peer->af_group[afi][safi])
3646 continue;
3647
3648 if (filter->dlist[direct].name)
3649 free (filter->dlist[direct].name);
3650 filter->dlist[direct].name = strdup (name);
3651 filter->dlist[direct].alist = access_list_lookup (afi, name);
3652 }
3653
3654 return 0;
3655}
3656
3657int
3658peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3659{
3660 struct bgp_filter *filter;
3661 struct bgp_filter *gfilter;
3662 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003663 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003664
3665 if (! peer->afc[afi][safi])
3666 return BGP_ERR_PEER_INACTIVE;
3667
3668 if (direct != FILTER_IN && direct != FILTER_OUT)
3669 return BGP_ERR_INVALID_VALUE;
3670
3671 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3672 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3673
3674 filter = &peer->filter[afi][safi];
3675
3676 /* apply peer-group filter */
3677 if (peer->af_group[afi][safi])
3678 {
3679 gfilter = &peer->group->conf->filter[afi][safi];
3680
3681 if (gfilter->dlist[direct].name)
3682 {
3683 if (filter->dlist[direct].name)
3684 free (filter->dlist[direct].name);
3685 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3686 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3687 return 0;
3688 }
3689 }
3690
3691 if (filter->dlist[direct].name)
3692 free (filter->dlist[direct].name);
3693 filter->dlist[direct].name = NULL;
3694 filter->dlist[direct].alist = NULL;
3695
3696 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3697 return 0;
3698
3699 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003700 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003701 {
3702 filter = &peer->filter[afi][safi];
3703
3704 if (! peer->af_group[afi][safi])
3705 continue;
3706
3707 if (filter->dlist[direct].name)
3708 free (filter->dlist[direct].name);
3709 filter->dlist[direct].name = NULL;
3710 filter->dlist[direct].alist = NULL;
3711 }
3712
3713 return 0;
3714}
3715
3716/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003717static void
paul718e3742002-12-13 20:15:29 +00003718peer_distribute_update (struct access_list *access)
3719{
3720 afi_t afi;
3721 safi_t safi;
3722 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003723 struct listnode *mnode, *mnnode;
3724 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003725 struct bgp *bgp;
3726 struct peer *peer;
3727 struct peer_group *group;
3728 struct bgp_filter *filter;
3729
paul1eb8ef22005-04-07 07:30:20 +00003730 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003731 {
paul1eb8ef22005-04-07 07:30:20 +00003732 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003733 {
3734 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3735 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3736 {
3737 filter = &peer->filter[afi][safi];
3738
3739 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3740 {
3741 if (filter->dlist[direct].name)
3742 filter->dlist[direct].alist =
3743 access_list_lookup (afi, filter->dlist[direct].name);
3744 else
3745 filter->dlist[direct].alist = NULL;
3746 }
3747 }
3748 }
paul1eb8ef22005-04-07 07:30:20 +00003749 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003750 {
3751 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3752 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3753 {
3754 filter = &group->conf->filter[afi][safi];
3755
3756 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3757 {
3758 if (filter->dlist[direct].name)
3759 filter->dlist[direct].alist =
3760 access_list_lookup (afi, filter->dlist[direct].name);
3761 else
3762 filter->dlist[direct].alist = NULL;
3763 }
3764 }
3765 }
3766 }
3767}
3768
3769/* Set prefix list to the peer. */
3770int
3771peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003772 const char *name)
paul718e3742002-12-13 20:15:29 +00003773{
3774 struct bgp_filter *filter;
3775 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003776 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003777
3778 if (! peer->afc[afi][safi])
3779 return BGP_ERR_PEER_INACTIVE;
3780
3781 if (direct != FILTER_IN && direct != FILTER_OUT)
3782 return BGP_ERR_INVALID_VALUE;
3783
3784 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3785 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3786
3787 filter = &peer->filter[afi][safi];
3788
3789 if (filter->dlist[direct].name)
3790 return BGP_ERR_PEER_FILTER_CONFLICT;
3791
3792 if (filter->plist[direct].name)
3793 free (filter->plist[direct].name);
3794 filter->plist[direct].name = strdup (name);
3795 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3796
3797 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3798 return 0;
3799
3800 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003801 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003802 {
3803 filter = &peer->filter[afi][safi];
3804
3805 if (! peer->af_group[afi][safi])
3806 continue;
3807
3808 if (filter->plist[direct].name)
3809 free (filter->plist[direct].name);
3810 filter->plist[direct].name = strdup (name);
3811 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3812 }
3813 return 0;
3814}
3815
3816int
3817peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3818{
3819 struct bgp_filter *filter;
3820 struct bgp_filter *gfilter;
3821 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003822 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003823
3824 if (! peer->afc[afi][safi])
3825 return BGP_ERR_PEER_INACTIVE;
3826
3827 if (direct != FILTER_IN && direct != FILTER_OUT)
3828 return BGP_ERR_INVALID_VALUE;
3829
3830 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3831 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3832
3833 filter = &peer->filter[afi][safi];
3834
3835 /* apply peer-group filter */
3836 if (peer->af_group[afi][safi])
3837 {
3838 gfilter = &peer->group->conf->filter[afi][safi];
3839
3840 if (gfilter->plist[direct].name)
3841 {
3842 if (filter->plist[direct].name)
3843 free (filter->plist[direct].name);
3844 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3845 filter->plist[direct].plist = gfilter->plist[direct].plist;
3846 return 0;
3847 }
3848 }
3849
3850 if (filter->plist[direct].name)
3851 free (filter->plist[direct].name);
3852 filter->plist[direct].name = NULL;
3853 filter->plist[direct].plist = NULL;
3854
3855 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3856 return 0;
3857
3858 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003859 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003860 {
3861 filter = &peer->filter[afi][safi];
3862
3863 if (! peer->af_group[afi][safi])
3864 continue;
3865
3866 if (filter->plist[direct].name)
3867 free (filter->plist[direct].name);
3868 filter->plist[direct].name = NULL;
3869 filter->plist[direct].plist = NULL;
3870 }
3871
3872 return 0;
3873}
3874
3875/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003876static void
paul718e3742002-12-13 20:15:29 +00003877peer_prefix_list_update (struct prefix_list *plist)
3878{
paul1eb8ef22005-04-07 07:30:20 +00003879 struct listnode *mnode, *mnnode;
3880 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003881 struct bgp *bgp;
3882 struct peer *peer;
3883 struct peer_group *group;
3884 struct bgp_filter *filter;
3885 afi_t afi;
3886 safi_t safi;
3887 int direct;
3888
paul1eb8ef22005-04-07 07:30:20 +00003889 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003890 {
paul1eb8ef22005-04-07 07:30:20 +00003891 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003892 {
3893 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3894 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3895 {
3896 filter = &peer->filter[afi][safi];
3897
3898 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3899 {
3900 if (filter->plist[direct].name)
3901 filter->plist[direct].plist =
3902 prefix_list_lookup (afi, filter->plist[direct].name);
3903 else
3904 filter->plist[direct].plist = NULL;
3905 }
3906 }
3907 }
paul1eb8ef22005-04-07 07:30:20 +00003908 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003909 {
3910 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3911 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3912 {
3913 filter = &group->conf->filter[afi][safi];
3914
3915 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3916 {
3917 if (filter->plist[direct].name)
3918 filter->plist[direct].plist =
3919 prefix_list_lookup (afi, filter->plist[direct].name);
3920 else
3921 filter->plist[direct].plist = NULL;
3922 }
3923 }
3924 }
3925 }
3926}
3927
3928int
3929peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003930 const char *name)
paul718e3742002-12-13 20:15:29 +00003931{
3932 struct bgp_filter *filter;
3933 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003934 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003935
3936 if (! peer->afc[afi][safi])
3937 return BGP_ERR_PEER_INACTIVE;
3938
3939 if (direct != FILTER_IN && direct != FILTER_OUT)
3940 return BGP_ERR_INVALID_VALUE;
3941
3942 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3943 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3944
3945 filter = &peer->filter[afi][safi];
3946
3947 if (filter->aslist[direct].name)
3948 free (filter->aslist[direct].name);
3949 filter->aslist[direct].name = strdup (name);
3950 filter->aslist[direct].aslist = as_list_lookup (name);
3951
3952 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3953 return 0;
3954
3955 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003956 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003957 {
3958 filter = &peer->filter[afi][safi];
3959
3960 if (! peer->af_group[afi][safi])
3961 continue;
3962
3963 if (filter->aslist[direct].name)
3964 free (filter->aslist[direct].name);
3965 filter->aslist[direct].name = strdup (name);
3966 filter->aslist[direct].aslist = as_list_lookup (name);
3967 }
3968 return 0;
3969}
3970
3971int
3972peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3973{
3974 struct bgp_filter *filter;
3975 struct bgp_filter *gfilter;
3976 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003977 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003978
3979 if (! peer->afc[afi][safi])
3980 return BGP_ERR_PEER_INACTIVE;
3981
hassob5f29602005-05-25 21:00:28 +00003982 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003983 return BGP_ERR_INVALID_VALUE;
3984
hassob5f29602005-05-25 21:00:28 +00003985 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003986 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3987
3988 filter = &peer->filter[afi][safi];
3989
3990 /* apply peer-group filter */
3991 if (peer->af_group[afi][safi])
3992 {
3993 gfilter = &peer->group->conf->filter[afi][safi];
3994
3995 if (gfilter->aslist[direct].name)
3996 {
3997 if (filter->aslist[direct].name)
3998 free (filter->aslist[direct].name);
3999 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4000 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4001 return 0;
4002 }
4003 }
4004
4005 if (filter->aslist[direct].name)
4006 free (filter->aslist[direct].name);
4007 filter->aslist[direct].name = NULL;
4008 filter->aslist[direct].aslist = NULL;
4009
4010 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4011 return 0;
4012
4013 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004014 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004015 {
4016 filter = &peer->filter[afi][safi];
4017
4018 if (! peer->af_group[afi][safi])
4019 continue;
4020
4021 if (filter->aslist[direct].name)
4022 free (filter->aslist[direct].name);
4023 filter->aslist[direct].name = NULL;
4024 filter->aslist[direct].aslist = NULL;
4025 }
4026
4027 return 0;
4028}
4029
paul94f2b392005-06-28 12:44:16 +00004030static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004031peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004032{
4033 afi_t afi;
4034 safi_t safi;
4035 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004036 struct listnode *mnode, *mnnode;
4037 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004038 struct bgp *bgp;
4039 struct peer *peer;
4040 struct peer_group *group;
4041 struct bgp_filter *filter;
4042
paul1eb8ef22005-04-07 07:30:20 +00004043 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004044 {
paul1eb8ef22005-04-07 07:30:20 +00004045 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004046 {
4047 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4048 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4049 {
4050 filter = &peer->filter[afi][safi];
4051
4052 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4053 {
4054 if (filter->aslist[direct].name)
4055 filter->aslist[direct].aslist =
4056 as_list_lookup (filter->aslist[direct].name);
4057 else
4058 filter->aslist[direct].aslist = NULL;
4059 }
4060 }
4061 }
paul1eb8ef22005-04-07 07:30:20 +00004062 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004063 {
4064 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4065 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4066 {
4067 filter = &group->conf->filter[afi][safi];
4068
4069 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4070 {
4071 if (filter->aslist[direct].name)
4072 filter->aslist[direct].aslist =
4073 as_list_lookup (filter->aslist[direct].name);
4074 else
4075 filter->aslist[direct].aslist = NULL;
4076 }
4077 }
4078 }
4079 }
4080}
4081
4082/* Set route-map to the peer. */
4083int
4084peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004085 const char *name)
paul718e3742002-12-13 20:15:29 +00004086{
4087 struct bgp_filter *filter;
4088 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004089 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004090
4091 if (! peer->afc[afi][safi])
4092 return BGP_ERR_PEER_INACTIVE;
4093
paulfee0f4c2004-09-13 05:12:46 +00004094 if (direct != RMAP_IN && direct != RMAP_OUT &&
4095 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004096 return BGP_ERR_INVALID_VALUE;
4097
paulfee0f4c2004-09-13 05:12:46 +00004098 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4099 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004100 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4101
4102 filter = &peer->filter[afi][safi];
4103
4104 if (filter->map[direct].name)
4105 free (filter->map[direct].name);
4106
4107 filter->map[direct].name = strdup (name);
4108 filter->map[direct].map = route_map_lookup_by_name (name);
4109
4110 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4111 return 0;
4112
4113 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004114 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004115 {
4116 filter = &peer->filter[afi][safi];
4117
4118 if (! peer->af_group[afi][safi])
4119 continue;
4120
4121 if (filter->map[direct].name)
4122 free (filter->map[direct].name);
4123 filter->map[direct].name = strdup (name);
4124 filter->map[direct].map = route_map_lookup_by_name (name);
4125 }
4126 return 0;
4127}
4128
4129/* Unset route-map from the peer. */
4130int
4131peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4132{
4133 struct bgp_filter *filter;
4134 struct bgp_filter *gfilter;
4135 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004136 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004137
4138 if (! peer->afc[afi][safi])
4139 return BGP_ERR_PEER_INACTIVE;
4140
hassob5f29602005-05-25 21:00:28 +00004141 if (direct != RMAP_IN && direct != RMAP_OUT &&
4142 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004143 return BGP_ERR_INVALID_VALUE;
4144
hassob5f29602005-05-25 21:00:28 +00004145 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4146 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004147 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4148
4149 filter = &peer->filter[afi][safi];
4150
4151 /* apply peer-group filter */
4152 if (peer->af_group[afi][safi])
4153 {
4154 gfilter = &peer->group->conf->filter[afi][safi];
4155
4156 if (gfilter->map[direct].name)
4157 {
4158 if (filter->map[direct].name)
4159 free (filter->map[direct].name);
4160 filter->map[direct].name = strdup (gfilter->map[direct].name);
4161 filter->map[direct].map = gfilter->map[direct].map;
4162 return 0;
4163 }
4164 }
4165
4166 if (filter->map[direct].name)
4167 free (filter->map[direct].name);
4168 filter->map[direct].name = NULL;
4169 filter->map[direct].map = NULL;
4170
4171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4172 return 0;
4173
4174 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004175 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004176 {
4177 filter = &peer->filter[afi][safi];
4178
4179 if (! peer->af_group[afi][safi])
4180 continue;
4181
4182 if (filter->map[direct].name)
4183 free (filter->map[direct].name);
4184 filter->map[direct].name = NULL;
4185 filter->map[direct].map = NULL;
4186 }
4187 return 0;
4188}
4189
4190/* Set unsuppress-map to the peer. */
4191int
paulfd79ac92004-10-13 05:06:08 +00004192peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4193 const char *name)
paul718e3742002-12-13 20:15:29 +00004194{
4195 struct bgp_filter *filter;
4196 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004197 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004198
4199 if (! peer->afc[afi][safi])
4200 return BGP_ERR_PEER_INACTIVE;
4201
4202 if (peer_is_group_member (peer, afi, safi))
4203 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4204
4205 filter = &peer->filter[afi][safi];
4206
4207 if (filter->usmap.name)
4208 free (filter->usmap.name);
4209
4210 filter->usmap.name = strdup (name);
4211 filter->usmap.map = route_map_lookup_by_name (name);
4212
4213 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4214 return 0;
4215
4216 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004217 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004218 {
4219 filter = &peer->filter[afi][safi];
4220
4221 if (! peer->af_group[afi][safi])
4222 continue;
4223
4224 if (filter->usmap.name)
4225 free (filter->usmap.name);
4226 filter->usmap.name = strdup (name);
4227 filter->usmap.map = route_map_lookup_by_name (name);
4228 }
4229 return 0;
4230}
4231
4232/* Unset route-map from the peer. */
4233int
4234peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4235{
4236 struct bgp_filter *filter;
4237 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004238 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004239
4240 if (! peer->afc[afi][safi])
4241 return BGP_ERR_PEER_INACTIVE;
4242
4243 if (peer_is_group_member (peer, afi, safi))
4244 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4245
4246 filter = &peer->filter[afi][safi];
4247
4248 if (filter->usmap.name)
4249 free (filter->usmap.name);
4250 filter->usmap.name = NULL;
4251 filter->usmap.map = NULL;
4252
4253 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4254 return 0;
4255
4256 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004257 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004258 {
4259 filter = &peer->filter[afi][safi];
4260
4261 if (! peer->af_group[afi][safi])
4262 continue;
4263
4264 if (filter->usmap.name)
4265 free (filter->usmap.name);
4266 filter->usmap.name = NULL;
4267 filter->usmap.map = NULL;
4268 }
4269 return 0;
4270}
4271
4272int
4273peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004274 u_int32_t max, u_char threshold,
4275 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004276{
4277 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004278 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004279
4280 if (! peer->afc[afi][safi])
4281 return BGP_ERR_PEER_INACTIVE;
4282
4283 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4284 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004285 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004286 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004287 if (warning)
4288 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4289 else
4290 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4291
4292 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4293 return 0;
4294
4295 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004296 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004297 {
4298 if (! peer->af_group[afi][safi])
4299 continue;
4300
4301 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4302 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004303 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004304 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004305 if (warning)
4306 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4307 else
4308 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4309 }
4310 return 0;
4311}
4312
4313int
4314peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4315{
4316 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004317 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004318
4319 if (! peer->afc[afi][safi])
4320 return BGP_ERR_PEER_INACTIVE;
4321
4322 /* apply peer-group config */
4323 if (peer->af_group[afi][safi])
4324 {
4325 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4326 PEER_FLAG_MAX_PREFIX))
4327 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4328 else
4329 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4330
4331 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4332 PEER_FLAG_MAX_PREFIX_WARNING))
4333 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4334 else
4335 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4336
4337 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004338 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004339 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004340 return 0;
4341 }
4342
4343 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4344 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4345 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004346 peer->pmax_threshold[afi][safi] = 0;
4347 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004348
4349 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4350 return 0;
4351
4352 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004353 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004354 {
4355 if (! peer->af_group[afi][safi])
4356 continue;
4357
4358 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4359 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4360 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004361 peer->pmax_threshold[afi][safi] = 0;
4362 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004363 }
4364 return 0;
4365}
4366
Nick Hilliardfa411a22011-03-23 15:33:17 +00004367/* Set # of hops between us and BGP peer. */
4368int
4369peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4370{
4371 struct peer_group *group;
4372 struct listnode *node, *nnode;
4373 struct peer *peer1;
4374 int ret;
4375
4376 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4377
4378 if (peer_sort (peer) == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004379 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004380
4381 /* We cannot configure ttl-security hops when ebgp-multihop is already
4382 set. For non peer-groups, the check is simple. For peer-groups, it's
4383 slightly messy, because we need to check both the peer-group structure
4384 and all peer-group members for any trace of ebgp-multihop configuration
4385 before actually applying the ttl-security rules. Cisco really made a
4386 mess of this configuration parameter, and OpenBGPD got it right.
4387 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004388
4389 if (peer->gtsm_hops == 0) {
4390 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4391 {
4392 group = peer->group;
4393 if (group->conf->ttl != 1)
4394 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004395
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004396 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4397 {
4398 if (peer_sort (peer1) == BGP_PEER_IBGP)
4399 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004400
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004401 if (peer1->ttl != 1)
4402 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4403 }
4404 }
4405 else
4406 {
4407 if (peer->ttl != 1)
4408 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4409 }
4410 /* specify MAXTTL on outgoing packets */
4411 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4412 if (ret != 0)
4413 return ret;
4414 }
4415
Nick Hilliardfa411a22011-03-23 15:33:17 +00004416 peer->gtsm_hops = gtsm_hops;
4417
Nick Hilliardfa411a22011-03-23 15:33:17 +00004418 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4419 {
4420 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4421 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4422 }
4423 else
4424 {
4425 group = peer->group;
4426 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4427 {
4428 if (peer_sort (peer) == BGP_PEER_IBGP)
4429 continue;
4430
4431 peer->gtsm_hops = group->conf->gtsm_hops;
4432
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004433 /* Change setting of existing peer
4434 * established then change value (may break connectivity)
4435 * not established yet (teardown session and restart)
4436 * no session then do nothing (will get handled by next connection)
4437 */
4438 if (peer->status == Established)
4439 {
4440 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4441 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4442 MAXTTL + 1 - peer->gtsm_hops);
4443 }
4444 else if (peer->status < Established)
4445 {
4446 if (BGP_DEBUG (events, EVENTS))
4447 zlog_debug ("%s Min-ttl changed", peer->host);
4448 BGP_EVENT_ADD (peer, BGP_Stop);
4449 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004450 }
4451 }
4452
4453 return 0;
4454}
4455
4456int
4457peer_ttl_security_hops_unset (struct peer *peer)
4458{
4459 struct peer_group *group;
4460 struct listnode *node, *nnode;
4461 struct peer *opeer;
4462
4463 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4464
4465 if (peer_sort (peer) == BGP_PEER_IBGP)
4466 return 0;
4467
4468 /* if a peer-group member, then reset to peer-group default rather than 0 */
4469 if (peer_group_active (peer))
4470 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4471 else
4472 peer->gtsm_hops = 0;
4473
4474 opeer = peer;
4475 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4476 {
4477 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4478 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4479 }
4480 else
4481 {
4482 group = peer->group;
4483 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4484 {
4485 if (peer_sort (peer) == BGP_PEER_IBGP)
4486 continue;
4487
4488 peer->gtsm_hops = 0;
4489
4490 if (peer->fd >= 0)
4491 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4492 }
4493 }
4494
4495 return peer_ebgp_multihop_unset (opeer);
4496}
4497
paul718e3742002-12-13 20:15:29 +00004498int
4499peer_clear (struct peer *peer)
4500{
4501 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4502 {
hasso0a486e52005-02-01 20:57:17 +00004503 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4504 {
4505 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4506 if (peer->t_pmax_restart)
4507 {
4508 BGP_TIMER_OFF (peer->t_pmax_restart);
4509 if (BGP_DEBUG (events, EVENTS))
4510 zlog_debug ("%s Maximum-prefix restart timer canceled",
4511 peer->host);
4512 }
4513 BGP_EVENT_ADD (peer, BGP_Start);
4514 return 0;
4515 }
4516
paul718e3742002-12-13 20:15:29 +00004517 peer->v_start = BGP_INIT_START_TIMER;
4518 if (peer->status == Established)
4519 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4520 BGP_NOTIFY_CEASE_ADMIN_RESET);
4521 else
4522 BGP_EVENT_ADD (peer, BGP_Stop);
4523 }
4524 return 0;
4525}
4526
4527int
4528peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4529 enum bgp_clear_type stype)
4530{
4531 if (peer->status != Established)
4532 return 0;
4533
4534 if (! peer->afc[afi][safi])
4535 return BGP_ERR_AF_UNCONFIGURED;
4536
paulfee0f4c2004-09-13 05:12:46 +00004537 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4538 {
4539 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4540 return 0;
4541 bgp_check_local_routes_rsclient (peer, afi, safi);
4542 bgp_soft_reconfig_rsclient (peer, afi, safi);
4543 }
4544
paul718e3742002-12-13 20:15:29 +00004545 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4546 bgp_announce_route (peer, afi, safi);
4547
4548 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4549 {
4550 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4551 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4552 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4553 {
4554 struct bgp_filter *filter = &peer->filter[afi][safi];
4555 u_char prefix_type;
4556
4557 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4558 prefix_type = ORF_TYPE_PREFIX;
4559 else
4560 prefix_type = ORF_TYPE_PREFIX_OLD;
4561
4562 if (filter->plist[FILTER_IN].plist)
4563 {
4564 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4565 bgp_route_refresh_send (peer, afi, safi,
4566 prefix_type, REFRESH_DEFER, 1);
4567 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4568 REFRESH_IMMEDIATE, 0);
4569 }
4570 else
4571 {
4572 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4573 bgp_route_refresh_send (peer, afi, safi,
4574 prefix_type, REFRESH_IMMEDIATE, 1);
4575 else
4576 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4577 }
4578 return 0;
4579 }
4580 }
4581
4582 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4583 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4584 {
4585 /* If neighbor has soft reconfiguration inbound flag.
4586 Use Adj-RIB-In database. */
4587 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4588 bgp_soft_reconfig_in (peer, afi, safi);
4589 else
4590 {
4591 /* If neighbor has route refresh capability, send route refresh
4592 message to the peer. */
4593 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4594 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4595 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4596 else
4597 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4598 }
4599 }
4600 return 0;
4601}
4602
paulfd79ac92004-10-13 05:06:08 +00004603/* Display peer uptime.*/
4604/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004605char *
4606peer_uptime (time_t uptime2, char *buf, size_t len)
4607{
4608 time_t uptime1;
4609 struct tm *tm;
4610
4611 /* Check buffer length. */
4612 if (len < BGP_UPTIME_LEN)
4613 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004614 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004615 /* XXX: should return status instead of buf... */
4616 snprintf (buf, len, "<error> ");
4617 return buf;
paul718e3742002-12-13 20:15:29 +00004618 }
4619
4620 /* If there is no connection has been done before print `never'. */
4621 if (uptime2 == 0)
4622 {
4623 snprintf (buf, len, "never ");
4624 return buf;
4625 }
4626
4627 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004628 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004629 uptime1 -= uptime2;
4630 tm = gmtime (&uptime1);
4631
4632 /* Making formatted timer strings. */
4633#define ONE_DAY_SECOND 60*60*24
4634#define ONE_WEEK_SECOND 60*60*24*7
4635
4636 if (uptime1 < ONE_DAY_SECOND)
4637 snprintf (buf, len, "%02d:%02d:%02d",
4638 tm->tm_hour, tm->tm_min, tm->tm_sec);
4639 else if (uptime1 < ONE_WEEK_SECOND)
4640 snprintf (buf, len, "%dd%02dh%02dm",
4641 tm->tm_yday, tm->tm_hour, tm->tm_min);
4642 else
4643 snprintf (buf, len, "%02dw%dd%02dh",
4644 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4645 return buf;
4646}
4647
paul94f2b392005-06-28 12:44:16 +00004648static void
paul718e3742002-12-13 20:15:29 +00004649bgp_config_write_filter (struct vty *vty, struct peer *peer,
4650 afi_t afi, safi_t safi)
4651{
4652 struct bgp_filter *filter;
4653 struct bgp_filter *gfilter = NULL;
4654 char *addr;
4655 int in = FILTER_IN;
4656 int out = FILTER_OUT;
4657
4658 addr = peer->host;
4659 filter = &peer->filter[afi][safi];
4660 if (peer->af_group[afi][safi])
4661 gfilter = &peer->group->conf->filter[afi][safi];
4662
4663 /* distribute-list. */
4664 if (filter->dlist[in].name)
4665 if (! gfilter || ! gfilter->dlist[in].name
4666 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4667 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4668 filter->dlist[in].name, VTY_NEWLINE);
4669 if (filter->dlist[out].name && ! gfilter)
4670 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4671 filter->dlist[out].name, VTY_NEWLINE);
4672
4673 /* prefix-list. */
4674 if (filter->plist[in].name)
4675 if (! gfilter || ! gfilter->plist[in].name
4676 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4677 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4678 filter->plist[in].name, VTY_NEWLINE);
4679 if (filter->plist[out].name && ! gfilter)
4680 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4681 filter->plist[out].name, VTY_NEWLINE);
4682
4683 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004684 if (filter->map[RMAP_IN].name)
4685 if (! gfilter || ! gfilter->map[RMAP_IN].name
4686 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004687 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004688 filter->map[RMAP_IN].name, VTY_NEWLINE);
4689 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004690 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004691 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4692 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4693 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4694 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4695 if (filter->map[RMAP_EXPORT].name)
4696 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4697 || strcmp (filter->map[RMAP_EXPORT].name,
4698 gfilter->map[RMAP_EXPORT].name) != 0)
4699 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4700 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004701
4702 /* unsuppress-map */
4703 if (filter->usmap.name && ! gfilter)
4704 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4705 filter->usmap.name, VTY_NEWLINE);
4706
4707 /* filter-list. */
4708 if (filter->aslist[in].name)
4709 if (! gfilter || ! gfilter->aslist[in].name
4710 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4711 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4712 filter->aslist[in].name, VTY_NEWLINE);
4713 if (filter->aslist[out].name && ! gfilter)
4714 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4715 filter->aslist[out].name, VTY_NEWLINE);
4716}
4717
4718/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004719static void
paul718e3742002-12-13 20:15:29 +00004720bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4721 struct peer *peer, afi_t afi, safi_t safi)
4722{
4723 struct bgp_filter *filter;
4724 struct peer *g_peer = NULL;
4725 char buf[SU_ADDRSTRLEN];
4726 char *addr;
4727
4728 filter = &peer->filter[afi][safi];
4729 addr = peer->host;
4730 if (peer_group_active (peer))
4731 g_peer = peer->group->conf;
4732
4733 /************************************
4734 ****** Global to the neighbor ******
4735 ************************************/
4736 if (afi == AFI_IP && safi == SAFI_UNICAST)
4737 {
4738 /* remote-as. */
4739 if (! peer_group_active (peer))
4740 {
4741 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4742 vty_out (vty, " neighbor %s peer-group%s", addr,
4743 VTY_NEWLINE);
4744 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004745 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004746 VTY_NEWLINE);
4747 }
4748 else
4749 {
4750 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004751 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004752 VTY_NEWLINE);
4753 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4754 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4755 peer->group->name, VTY_NEWLINE);
4756 }
4757
4758 /* local-as. */
4759 if (peer->change_local_as)
4760 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004761 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004762 peer->change_local_as,
4763 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4764 " no-prepend" : "", VTY_NEWLINE);
4765
4766 /* Description. */
4767 if (peer->desc)
4768 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4769 VTY_NEWLINE);
4770
4771 /* Shutdown. */
4772 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4773 if (! peer_group_active (peer) ||
4774 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4775 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4776
Paul Jakma0df7c912008-07-21 21:02:49 +00004777 /* Password. */
4778 if (peer->password)
4779 if (!peer_group_active (peer)
4780 || ! g_peer->password
4781 || strcmp (peer->password, g_peer->password) != 0)
4782 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4783 VTY_NEWLINE);
4784
paul718e3742002-12-13 20:15:29 +00004785 /* BGP port. */
4786 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004787 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004788 VTY_NEWLINE);
4789
4790 /* Local interface name. */
4791 if (peer->ifname)
4792 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4793 VTY_NEWLINE);
4794
4795 /* Passive. */
4796 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4797 if (! peer_group_active (peer) ||
4798 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4799 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4800
4801 /* EBGP multihop. */
Nick Hilliardfa411a22011-03-23 15:33:17 +00004802 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
4803 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004804 if (! peer_group_active (peer) ||
4805 g_peer->ttl != peer->ttl)
4806 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4807 VTY_NEWLINE);
4808
Nick Hilliardfa411a22011-03-23 15:33:17 +00004809 /* ttl-security hops */
4810 if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
4811 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004812 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004813 peer->gtsm_hops, VTY_NEWLINE);
4814
hasso6ffd2072005-02-02 14:50:11 +00004815 /* disable-connected-check. */
4816 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004817 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004818 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4819 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004820
4821 /* Update-source. */
4822 if (peer->update_if)
4823 if (! peer_group_active (peer) || ! g_peer->update_if
4824 || strcmp (g_peer->update_if, peer->update_if) != 0)
4825 vty_out (vty, " neighbor %s update-source %s%s", addr,
4826 peer->update_if, VTY_NEWLINE);
4827 if (peer->update_source)
4828 if (! peer_group_active (peer) || ! g_peer->update_source
4829 || sockunion_cmp (g_peer->update_source,
4830 peer->update_source) != 0)
4831 vty_out (vty, " neighbor %s update-source %s%s", addr,
4832 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4833 VTY_NEWLINE);
4834
paul718e3742002-12-13 20:15:29 +00004835 /* advertisement-interval */
4836 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4837 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4838 addr, peer->v_routeadv, VTY_NEWLINE);
4839
4840 /* timers. */
4841 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4842 && ! peer_group_active (peer))
4843 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4844 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4845
4846 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4847 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4848 peer->connect, VTY_NEWLINE);
4849
4850 /* Default weight. */
4851 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4852 if (! peer_group_active (peer) ||
4853 g_peer->weight != peer->weight)
4854 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4855 VTY_NEWLINE);
4856
paul718e3742002-12-13 20:15:29 +00004857 /* Dynamic capability. */
4858 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4859 if (! peer_group_active (peer) ||
4860 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4861 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4862 VTY_NEWLINE);
4863
4864 /* dont capability negotiation. */
4865 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4866 if (! peer_group_active (peer) ||
4867 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4868 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4869 VTY_NEWLINE);
4870
4871 /* override capability negotiation. */
4872 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4873 if (! peer_group_active (peer) ||
4874 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4875 vty_out (vty, " neighbor %s override-capability%s", addr,
4876 VTY_NEWLINE);
4877
4878 /* strict capability negotiation. */
4879 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4880 if (! peer_group_active (peer) ||
4881 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4882 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4883 VTY_NEWLINE);
4884
4885 if (! peer_group_active (peer))
4886 {
4887 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4888 {
4889 if (peer->afc[AFI_IP][SAFI_UNICAST])
4890 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4891 }
4892 else
4893 {
4894 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4895 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4896 }
4897 }
4898 }
4899
4900
4901 /************************************
4902 ****** Per AF to the neighbor ******
4903 ************************************/
4904
4905 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4906 {
4907 if (peer->af_group[afi][safi])
4908 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4909 peer->group->name, VTY_NEWLINE);
4910 else
4911 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4912 }
4913
4914 /* ORF capability. */
4915 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4916 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4917 if (! peer->af_group[afi][safi])
4918 {
4919 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4920
4921 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4922 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4923 vty_out (vty, " both");
4924 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4925 vty_out (vty, " send");
4926 else
4927 vty_out (vty, " receive");
4928 vty_out (vty, "%s", VTY_NEWLINE);
4929 }
4930
4931 /* Route reflector client. */
4932 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4933 && ! peer->af_group[afi][safi])
4934 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4935 VTY_NEWLINE);
4936
4937 /* Nexthop self. */
4938 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4939 && ! peer->af_group[afi][safi])
4940 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4941
4942 /* Remove private AS. */
4943 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4944 && ! peer->af_group[afi][safi])
4945 vty_out (vty, " neighbor %s remove-private-AS%s",
4946 addr, VTY_NEWLINE);
4947
4948 /* send-community print. */
4949 if (! peer->af_group[afi][safi])
4950 {
4951 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4952 {
4953 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4954 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4955 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4956 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4957 vty_out (vty, " neighbor %s send-community extended%s",
4958 addr, VTY_NEWLINE);
4959 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4960 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4961 }
4962 else
4963 {
4964 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4965 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4966 vty_out (vty, " no neighbor %s send-community both%s",
4967 addr, VTY_NEWLINE);
4968 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4969 vty_out (vty, " no neighbor %s send-community extended%s",
4970 addr, VTY_NEWLINE);
4971 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4972 vty_out (vty, " no neighbor %s send-community%s",
4973 addr, VTY_NEWLINE);
4974 }
4975 }
4976
4977 /* Default information */
4978 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4979 && ! peer->af_group[afi][safi])
4980 {
4981 vty_out (vty, " neighbor %s default-originate", addr);
4982 if (peer->default_rmap[afi][safi].name)
4983 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4984 vty_out (vty, "%s", VTY_NEWLINE);
4985 }
4986
4987 /* Soft reconfiguration inbound. */
4988 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4989 if (! peer->af_group[afi][safi] ||
4990 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4991 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4992 VTY_NEWLINE);
4993
4994 /* maximum-prefix. */
4995 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4996 if (! peer->af_group[afi][safi]
4997 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004998 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004999 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5000 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005001 {
hasso0a486e52005-02-01 20:57:17 +00005002 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5003 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5004 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5005 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5006 vty_out (vty, " warning-only");
5007 if (peer->pmax_restart[afi][safi])
5008 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5009 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005010 }
paul718e3742002-12-13 20:15:29 +00005011
5012 /* Route server client. */
5013 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5014 && ! peer->af_group[afi][safi])
5015 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5016
5017 /* Allow AS in. */
5018 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5019 if (! peer_group_active (peer)
5020 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5021 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5022 {
5023 if (peer->allowas_in[afi][safi] == 3)
5024 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5025 else
5026 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5027 peer->allowas_in[afi][safi], VTY_NEWLINE);
5028 }
5029
5030 /* Filter. */
5031 bgp_config_write_filter (vty, peer, afi, safi);
5032
5033 /* atribute-unchanged. */
5034 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5035 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5036 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5037 && ! peer->af_group[afi][safi])
5038 {
5039 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5040 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5041 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5042 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5043 else
5044 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5045 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5046 " as-path" : "",
5047 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5048 " next-hop" : "",
5049 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5050 " med" : "", VTY_NEWLINE);
5051 }
5052}
5053
5054/* Display "address-family" configuration header. */
5055void
5056bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5057 int *write)
5058{
5059 if (*write)
5060 return;
5061
5062 if (afi == AFI_IP && safi == SAFI_UNICAST)
5063 return;
5064
5065 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5066
5067 if (afi == AFI_IP)
5068 {
5069 if (safi == SAFI_MULTICAST)
5070 vty_out (vty, "ipv4 multicast");
5071 else if (safi == SAFI_MPLS_VPN)
5072 vty_out (vty, "vpnv4 unicast");
5073 }
5074 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005075 {
5076 vty_out (vty, "ipv6");
5077
5078 if (safi == SAFI_MULTICAST)
5079 vty_out (vty, " multicast");
5080 }
paul718e3742002-12-13 20:15:29 +00005081
5082 vty_out (vty, "%s", VTY_NEWLINE);
5083
5084 *write = 1;
5085}
5086
5087/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005088static int
paul718e3742002-12-13 20:15:29 +00005089bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5090 safi_t safi)
5091{
5092 int write = 0;
5093 struct peer *peer;
5094 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005095 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005096
5097 bgp_config_write_network (vty, bgp, afi, safi, &write);
5098
5099 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5100
paul1eb8ef22005-04-07 07:30:20 +00005101 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005102 {
5103 if (group->conf->afc[afi][safi])
5104 {
5105 bgp_config_write_family_header (vty, afi, safi, &write);
5106 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5107 }
5108 }
paul1eb8ef22005-04-07 07:30:20 +00005109 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005110 {
5111 if (peer->afc[afi][safi])
5112 {
5113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5114 {
5115 bgp_config_write_family_header (vty, afi, safi, &write);
5116 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5117 }
5118 }
5119 }
5120 if (write)
5121 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5122
5123 return write;
5124}
5125
5126int
5127bgp_config_write (struct vty *vty)
5128{
5129 int write = 0;
5130 struct bgp *bgp;
5131 struct peer_group *group;
5132 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005133 struct listnode *node, *nnode;
5134 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005135
5136 /* BGP Multiple instance. */
5137 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5138 {
5139 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5140 write++;
5141 }
5142
5143 /* BGP Config type. */
5144 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5145 {
5146 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5147 write++;
5148 }
5149
5150 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005151 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005152 {
5153 if (write)
5154 vty_out (vty, "!%s", VTY_NEWLINE);
5155
5156 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005157 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005158
5159 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5160 {
5161 if (bgp->name)
5162 vty_out (vty, " view %s", bgp->name);
5163 }
5164 vty_out (vty, "%s", VTY_NEWLINE);
5165
5166 /* No Synchronization */
5167 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5168 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5169
5170 /* BGP fast-external-failover. */
5171 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5172 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5173
5174 /* BGP router ID. */
5175 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5176 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5177 VTY_NEWLINE);
5178
paul848973c2003-08-13 00:32:49 +00005179 /* BGP log-neighbor-changes. */
5180 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5181 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5182
paul718e3742002-12-13 20:15:29 +00005183 /* BGP configuration. */
5184 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5185 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5186
5187 /* BGP default ipv4-unicast. */
5188 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5189 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5190
5191 /* BGP default local-preference. */
5192 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5193 vty_out (vty, " bgp default local-preference %d%s",
5194 bgp->default_local_pref, VTY_NEWLINE);
5195
5196 /* BGP client-to-client reflection. */
5197 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5198 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5199
5200 /* BGP cluster ID. */
5201 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5202 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5203 VTY_NEWLINE);
5204
hassoe0701b72004-05-20 09:19:34 +00005205 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005206 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005207 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5208 VTY_NEWLINE);
5209
5210 /* Confederation peer */
5211 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005212 {
hassoe0701b72004-05-20 09:19:34 +00005213 int i;
paul718e3742002-12-13 20:15:29 +00005214
hassoe0701b72004-05-20 09:19:34 +00005215 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005216
hassoe0701b72004-05-20 09:19:34 +00005217 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005218 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005219
hassoe0701b72004-05-20 09:19:34 +00005220 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005221 }
5222
5223 /* BGP enforce-first-as. */
5224 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5225 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5226
5227 /* BGP deterministic-med. */
5228 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5229 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005230
5231 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005232 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5233 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5234 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005235 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5236 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5237
paul718e3742002-12-13 20:15:29 +00005238 /* BGP bestpath method. */
5239 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5240 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005241 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5242 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005243 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5244 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5245 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5246 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5247 {
5248 vty_out (vty, " bgp bestpath med");
5249 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5250 vty_out (vty, " confed");
5251 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5252 vty_out (vty, " missing-as-worst");
5253 vty_out (vty, "%s", VTY_NEWLINE);
5254 }
5255
5256 /* BGP network import check. */
5257 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5258 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5259
5260 /* BGP scan interval. */
5261 bgp_config_write_scan_time (vty);
5262
5263 /* BGP flag dampening. */
5264 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5265 BGP_CONFIG_DAMPENING))
5266 bgp_config_write_damp (vty);
5267
5268 /* BGP static route configuration. */
5269 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5270
5271 /* BGP redistribute configuration. */
5272 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5273
5274 /* BGP timers configuration. */
5275 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5276 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5277 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5278 bgp->default_holdtime, VTY_NEWLINE);
5279
5280 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005281 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005282 {
5283 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5284 }
5285
5286 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005287 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005288 {
5289 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5290 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5291 }
5292
5293 /* Distance configuration. */
5294 bgp_config_write_distance (vty, bgp);
5295
5296 /* No auto-summary */
5297 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5298 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5299
5300 /* IPv4 multicast configuration. */
5301 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5302
5303 /* IPv4 VPN configuration. */
5304 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5305
5306 /* IPv6 unicast configuration. */
5307 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5308
Paul Jakma37a217a2007-04-10 19:20:29 +00005309 /* IPv6 multicast configuration. */
5310 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5311
paul718e3742002-12-13 20:15:29 +00005312 write++;
5313 }
5314 return write;
5315}
5316
5317void
paul94f2b392005-06-28 12:44:16 +00005318bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005319{
5320 memset (&bgp_master, 0, sizeof (struct bgp_master));
5321
5322 bm = &bgp_master;
5323 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005324 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005325 bm->port = BGP_PORT_DEFAULT;
5326 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005327 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005328}
paul200df112005-06-01 11:17:05 +00005329
paul718e3742002-12-13 20:15:29 +00005330
5331void
paul94f2b392005-06-28 12:44:16 +00005332bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005333{
paul718e3742002-12-13 20:15:29 +00005334 /* BGP VTY commands installation. */
5335 bgp_vty_init ();
5336
paul718e3742002-12-13 20:15:29 +00005337 /* Init zebra. */
5338 bgp_zebra_init ();
5339
5340 /* BGP inits. */
5341 bgp_attr_init ();
5342 bgp_debug_init ();
5343 bgp_dump_init ();
5344 bgp_route_init ();
5345 bgp_route_map_init ();
5346 bgp_scan_init ();
5347 bgp_mplsvpn_init ();
5348
5349 /* Access list initialize. */
5350 access_list_init ();
5351 access_list_add_hook (peer_distribute_update);
5352 access_list_delete_hook (peer_distribute_update);
5353
5354 /* Filter list initialize. */
5355 bgp_filter_init ();
5356 as_list_add_hook (peer_aslist_update);
5357 as_list_delete_hook (peer_aslist_update);
5358
5359 /* Prefix list initialize.*/
5360 prefix_list_init ();
5361 prefix_list_add_hook (peer_prefix_list_update);
5362 prefix_list_delete_hook (peer_prefix_list_update);
5363
5364 /* Community list initialize. */
5365 bgp_clist = community_list_init ();
5366
5367#ifdef HAVE_SNMP
5368 bgp_snmp_init ();
5369#endif /* HAVE_SNMP */
5370}
paul545acaf2004-04-20 15:13:15 +00005371
5372void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005373bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005374{
paul545acaf2004-04-20 15:13:15 +00005375 struct bgp *bgp;
5376 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005377 struct listnode *node, *nnode;
5378 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005379
paul1eb8ef22005-04-07 07:30:20 +00005380 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5381 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005382 if (peer->status == Established)
5383 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5384 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005385
paul545acaf2004-04-20 15:13:15 +00005386 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005387
paule210cf92005-06-15 19:15:35 +00005388 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005389 {
5390 work_queue_free (bm->process_main_queue);
5391 bm->process_main_queue = NULL;
5392 }
paule210cf92005-06-15 19:15:35 +00005393 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005394 {
5395 work_queue_free (bm->process_rsclient_queue);
5396 bm->process_rsclient_queue = NULL;
5397 }
paul545acaf2004-04-20 15:13:15 +00005398}