blob: 5dc014be9bcb37faa084d9f4e07005e7bca5b312 [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
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100698static void
paul200df112005-06-01 11:17:05 +0000699peer_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
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002051 bgp = bgp_create (as, name);
2052 bgp_router_id_set(bgp, &router_id_zebra);
2053 *bgp_val = bgp;
2054
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002055 /* Create BGP server socket, if first instance. */
2056 if (list_isempty(bm->bgp))
2057 {
2058 if (bgp_socket (bm->port, bm->address) < 0)
2059 return BGP_ERR_INVALID_VALUE;
2060 }
2061
paul718e3742002-12-13 20:15:29 +00002062 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002063
2064 return 0;
2065}
2066
2067/* Delete BGP instance. */
2068int
2069bgp_delete (struct bgp *bgp)
2070{
2071 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002072 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002073 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002074 struct listnode *next;
2075 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002076 int i;
2077
2078 /* Delete static route. */
2079 bgp_static_delete (bgp);
2080
2081 /* Unset redistribution. */
2082 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2083 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2084 if (i != ZEBRA_ROUTE_BGP)
2085 bgp_redistribute_unset (bgp, afi, i);
2086
paul1eb8ef22005-04-07 07:30:20 +00002087 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2088 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002089
Chris Caputo228da422009-07-18 05:44:03 +00002090 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2091 peer_group_delete (group);
2092
2093 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002094
2095 if (bgp->peer_self) {
2096 peer_delete(bgp->peer_self);
2097 bgp->peer_self = NULL;
2098 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002099
2100 /* Remove visibility via the master list - there may however still be
2101 * routes to be processed still referencing the struct bgp.
2102 */
2103 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002104 if (list_isempty(bm->bgp))
2105 bgp_close ();
2106
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002107 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002108
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002109 return 0;
2110}
2111
2112static void bgp_free (struct bgp *);
2113
2114void
2115bgp_lock (struct bgp *bgp)
2116{
2117 ++bgp->lock;
2118}
2119
2120void
2121bgp_unlock(struct bgp *bgp)
2122{
Chris Caputo228da422009-07-18 05:44:03 +00002123 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002124 if (--bgp->lock == 0)
2125 bgp_free (bgp);
2126}
2127
2128static void
2129bgp_free (struct bgp *bgp)
2130{
2131 afi_t afi;
2132 safi_t safi;
2133
2134 list_delete (bgp->group);
2135 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002136 list_delete (bgp->rsclient);
2137
paul718e3742002-12-13 20:15:29 +00002138 if (bgp->name)
2139 free (bgp->name);
2140
2141 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2142 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2143 {
2144 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002145 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002146 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002147 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002148 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002149 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002150 }
2151 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002152}
2153
2154struct peer *
2155peer_lookup (struct bgp *bgp, union sockunion *su)
2156{
2157 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002158 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002159
Steve Hillfc4dc592009-07-28 17:54:35 +01002160 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002161 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002162 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2163 if (sockunion_same (&peer->su, su)
2164 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2165 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002166 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002167 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002168 {
2169 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002170
Paul Jakma2158ad22009-07-28 18:10:55 +01002171 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2173 if (sockunion_same (&peer->su, su)
2174 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2175 return peer;
paul718e3742002-12-13 20:15:29 +00002176 }
2177 return NULL;
2178}
2179
2180struct peer *
2181peer_lookup_with_open (union sockunion *su, as_t remote_as,
2182 struct in_addr *remote_id, int *as)
2183{
2184 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002185 struct listnode *node;
2186 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002187 struct bgp *bgp;
2188
Steve Hillfc4dc592009-07-28 17:54:35 +01002189 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002190 return NULL;
2191
Paul Jakma9d878772009-08-05 16:25:16 +01002192 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002193 {
Paul Jakma9d878772009-08-05 16:25:16 +01002194 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2195 {
2196 if (sockunion_same (&peer->su, su)
2197 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2198 {
2199 if (peer->as == remote_as
2200 && peer->remote_id.s_addr == remote_id->s_addr)
2201 return peer;
2202 if (peer->as == remote_as)
2203 *as = 1;
2204 }
2205 }
2206
2207 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2208 {
2209 if (sockunion_same (&peer->su, su)
2210 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2211 {
2212 if (peer->as == remote_as
2213 && peer->remote_id.s_addr == 0)
2214 return peer;
2215 if (peer->as == remote_as)
2216 *as = 1;
2217 }
2218 }
paul718e3742002-12-13 20:15:29 +00002219 }
2220 return NULL;
2221}
2222
2223/* If peer is configured at least one address family return 1. */
2224int
2225peer_active (struct peer *peer)
2226{
2227 if (peer->afc[AFI_IP][SAFI_UNICAST]
2228 || peer->afc[AFI_IP][SAFI_MULTICAST]
2229 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2230 || peer->afc[AFI_IP6][SAFI_UNICAST]
2231 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2232 return 1;
2233 return 0;
2234}
2235
2236/* If peer is negotiated at least one address family return 1. */
2237int
2238peer_active_nego (struct peer *peer)
2239{
2240 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2241 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2242 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2243 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2244 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2245 return 1;
2246 return 0;
2247}
2248
2249/* peer_flag_change_type. */
2250enum peer_change_type
2251{
2252 peer_change_none,
2253 peer_change_reset,
2254 peer_change_reset_in,
2255 peer_change_reset_out,
2256};
2257
paul94f2b392005-06-28 12:44:16 +00002258static void
paul718e3742002-12-13 20:15:29 +00002259peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2260 enum peer_change_type type)
2261{
2262 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2263 return;
2264
2265 if (type == peer_change_reset)
2266 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2267 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2268 else if (type == peer_change_reset_in)
2269 {
2270 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2271 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2272 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2273 else
2274 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2275 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2276 }
2277 else if (type == peer_change_reset_out)
2278 bgp_announce_route (peer, afi, safi);
2279}
2280
2281struct peer_flag_action
2282{
2283 /* Peer's flag. */
2284 u_int32_t flag;
2285
2286 /* This flag can be set for peer-group member. */
2287 u_char not_for_member;
2288
2289 /* Action when the flag is changed. */
2290 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002291
2292 /* Peer down cause */
2293 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002294};
2295
Stephen Hemminger03621952009-07-21 16:27:20 -07002296static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002297 {
2298 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2299 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2300 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2301 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2302 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002303 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002304 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002305 { 0, 0, 0 }
2306 };
2307
Stephen Hemminger03621952009-07-21 16:27:20 -07002308static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002309 {
2310 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2311 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2312 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2313 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2314 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2315 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2316 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2317 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2318 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2319 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2320 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2321 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2322 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002323 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002324 { 0, 0, 0 }
2325 };
2326
2327/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002328static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002329peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002330 struct peer_flag_action *action, u_int32_t flag)
2331{
2332 int i;
2333 int found = 0;
2334 int reset_in = 0;
2335 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002336 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002337
2338 /* Check peer's frag action. */
2339 for (i = 0; i < size; i++)
2340 {
2341 match = &action_list[i];
2342
2343 if (match->flag == 0)
2344 break;
2345
2346 if (match->flag & flag)
2347 {
2348 found = 1;
2349
2350 if (match->type == peer_change_reset_in)
2351 reset_in = 1;
2352 if (match->type == peer_change_reset_out)
2353 reset_out = 1;
2354 if (match->type == peer_change_reset)
2355 {
2356 reset_in = 1;
2357 reset_out = 1;
2358 }
2359 if (match->not_for_member)
2360 action->not_for_member = 1;
2361 }
2362 }
2363
2364 /* Set peer clear type. */
2365 if (reset_in && reset_out)
2366 action->type = peer_change_reset;
2367 else if (reset_in)
2368 action->type = peer_change_reset_in;
2369 else if (reset_out)
2370 action->type = peer_change_reset_out;
2371 else
2372 action->type = peer_change_none;
2373
2374 return found;
2375}
2376
paul94f2b392005-06-28 12:44:16 +00002377static void
paul718e3742002-12-13 20:15:29 +00002378peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2379{
2380 if (flag == PEER_FLAG_SHUTDOWN)
2381 {
2382 if (CHECK_FLAG (peer->flags, flag))
2383 {
hasso93406d82005-02-02 14:40:33 +00002384 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2385 peer_nsf_stop (peer);
2386
hasso0a486e52005-02-01 20:57:17 +00002387 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2388 if (peer->t_pmax_restart)
2389 {
2390 BGP_TIMER_OFF (peer->t_pmax_restart);
2391 if (BGP_DEBUG (events, EVENTS))
2392 zlog_debug ("%s Maximum-prefix restart timer canceled",
2393 peer->host);
2394 }
2395
hasso93406d82005-02-02 14:40:33 +00002396 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2397 peer_nsf_stop (peer);
2398
paul718e3742002-12-13 20:15:29 +00002399 if (peer->status == Established)
2400 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2401 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2402 else
2403 BGP_EVENT_ADD (peer, BGP_Stop);
2404 }
2405 else
2406 {
2407 peer->v_start = BGP_INIT_START_TIMER;
2408 BGP_EVENT_ADD (peer, BGP_Stop);
2409 }
2410 }
2411 else if (peer->status == Established)
2412 {
hassoc9502432005-02-01 22:01:48 +00002413 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2414 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2415 else if (flag == PEER_FLAG_PASSIVE)
2416 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002417 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002418 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002419
hassoc9502432005-02-01 22:01:48 +00002420 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2421 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002422 }
2423 else
2424 BGP_EVENT_ADD (peer, BGP_Stop);
2425}
2426
2427/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002428static int
paul718e3742002-12-13 20:15:29 +00002429peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2430{
2431 int found;
2432 int size;
2433 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002434 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002435 struct peer_flag_action action;
2436
2437 memset (&action, 0, sizeof (struct peer_flag_action));
2438 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2439
2440 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2441
2442 /* No flag action is found. */
2443 if (! found)
2444 return BGP_ERR_INVALID_FLAG;
2445
2446 /* Not for peer-group member. */
2447 if (action.not_for_member && peer_group_active (peer))
2448 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2449
2450 /* When unset the peer-group member's flag we have to check
2451 peer-group configuration. */
2452 if (! set && peer_group_active (peer))
2453 if (CHECK_FLAG (peer->group->conf->flags, flag))
2454 {
2455 if (flag == PEER_FLAG_SHUTDOWN)
2456 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2457 else
2458 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2459 }
2460
2461 /* Flag conflict check. */
2462 if (set
2463 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2464 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2465 return BGP_ERR_PEER_FLAG_CONFLICT;
2466
2467 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2468 {
2469 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2470 return 0;
2471 if (! set && ! CHECK_FLAG (peer->flags, flag))
2472 return 0;
2473 }
2474
2475 if (set)
2476 SET_FLAG (peer->flags, flag);
2477 else
2478 UNSET_FLAG (peer->flags, flag);
2479
2480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2481 {
2482 if (action.type == peer_change_reset)
2483 peer_flag_modify_action (peer, flag);
2484
2485 return 0;
2486 }
2487
2488 /* peer-group member updates. */
2489 group = peer->group;
2490
paul1eb8ef22005-04-07 07:30:20 +00002491 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002492 {
2493 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2494 continue;
2495
2496 if (! set && ! CHECK_FLAG (peer->flags, flag))
2497 continue;
2498
2499 if (set)
2500 SET_FLAG (peer->flags, flag);
2501 else
2502 UNSET_FLAG (peer->flags, flag);
2503
2504 if (action.type == peer_change_reset)
2505 peer_flag_modify_action (peer, flag);
2506 }
2507 return 0;
2508}
2509
2510int
2511peer_flag_set (struct peer *peer, u_int32_t flag)
2512{
2513 return peer_flag_modify (peer, flag, 1);
2514}
2515
2516int
2517peer_flag_unset (struct peer *peer, u_int32_t flag)
2518{
2519 return peer_flag_modify (peer, flag, 0);
2520}
2521
paul94f2b392005-06-28 12:44:16 +00002522static int
paul718e3742002-12-13 20:15:29 +00002523peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2524{
2525 if (peer->af_group[afi][safi])
2526 return 1;
2527 return 0;
2528}
2529
paul94f2b392005-06-28 12:44:16 +00002530static int
paul718e3742002-12-13 20:15:29 +00002531peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2532 int set)
2533{
2534 int found;
2535 int size;
paul1eb8ef22005-04-07 07:30:20 +00002536 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002537 struct peer_group *group;
2538 struct peer_flag_action action;
2539
2540 memset (&action, 0, sizeof (struct peer_flag_action));
2541 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2542
2543 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2544
2545 /* No flag action is found. */
2546 if (! found)
2547 return BGP_ERR_INVALID_FLAG;
2548
2549 /* Adress family must be activated. */
2550 if (! peer->afc[afi][safi])
2551 return BGP_ERR_PEER_INACTIVE;
2552
2553 /* Not for peer-group member. */
2554 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2555 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2556
2557 /* Spcecial check for reflector client. */
2558 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2559 && peer_sort (peer) != BGP_PEER_IBGP)
2560 return BGP_ERR_NOT_INTERNAL_PEER;
2561
2562 /* Spcecial check for remove-private-AS. */
2563 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2564 && peer_sort (peer) == BGP_PEER_IBGP)
2565 return BGP_ERR_REMOVE_PRIVATE_AS;
2566
2567 /* When unset the peer-group member's flag we have to check
2568 peer-group configuration. */
2569 if (! set && peer->af_group[afi][safi])
2570 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2571 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2572
2573 /* When current flag configuration is same as requested one. */
2574 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2575 {
2576 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2577 return 0;
2578 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2579 return 0;
2580 }
2581
2582 if (set)
2583 SET_FLAG (peer->af_flags[afi][safi], flag);
2584 else
2585 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2586
2587 /* Execute action when peer is established. */
2588 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2589 && peer->status == Established)
2590 {
2591 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2592 bgp_clear_adj_in (peer, afi, safi);
2593 else
hassoe0701b72004-05-20 09:19:34 +00002594 {
2595 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2596 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2597 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2598 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2599 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2600 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2601 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2602 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2603
2604 peer_change_action (peer, afi, safi, action.type);
2605 }
2606
paul718e3742002-12-13 20:15:29 +00002607 }
2608
2609 /* Peer group member updates. */
2610 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2611 {
2612 group = peer->group;
2613
paul1eb8ef22005-04-07 07:30:20 +00002614 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002615 {
2616 if (! peer->af_group[afi][safi])
2617 continue;
2618
2619 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2620 continue;
2621
2622 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2623 continue;
2624
2625 if (set)
2626 SET_FLAG (peer->af_flags[afi][safi], flag);
2627 else
2628 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2629
2630 if (peer->status == Established)
2631 {
2632 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2633 bgp_clear_adj_in (peer, afi, safi);
2634 else
hassoe0701b72004-05-20 09:19:34 +00002635 {
2636 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2637 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2638 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2639 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2640 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2641 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2642 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2643 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2644
2645 peer_change_action (peer, afi, safi, action.type);
2646 }
paul718e3742002-12-13 20:15:29 +00002647 }
2648 }
2649 }
2650 return 0;
2651}
2652
2653int
2654peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2655{
2656 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2657}
2658
2659int
2660peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2661{
2662 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2663}
2664
2665/* EBGP multihop configuration. */
2666int
2667peer_ebgp_multihop_set (struct peer *peer, int ttl)
2668{
2669 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002670 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002671 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002672
2673 if (peer_sort (peer) == BGP_PEER_IBGP)
2674 return 0;
2675
Nick Hilliardfa411a22011-03-23 15:33:17 +00002676 /* see comment in peer_ttl_security_hops_set() */
2677 if (ttl != MAXTTL)
2678 {
2679 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2680 {
2681 group = peer->group;
2682 if (group->conf->gtsm_hops != 0)
2683 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2684
2685 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2686 {
2687 if (peer_sort (peer1) == BGP_PEER_IBGP)
2688 continue;
2689
2690 if (peer1->gtsm_hops != 0)
2691 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2692 }
2693 }
2694 else
2695 {
2696 if (peer->gtsm_hops != 0)
2697 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2698 }
2699 }
2700
paul718e3742002-12-13 20:15:29 +00002701 peer->ttl = ttl;
2702
2703 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2704 {
pauleb821182004-05-01 08:44:08 +00002705 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2706 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002707 }
2708 else
2709 {
2710 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002711 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002712 {
2713 if (peer_sort (peer) == BGP_PEER_IBGP)
2714 continue;
paul718e3742002-12-13 20:15:29 +00002715
pauleb821182004-05-01 08:44:08 +00002716 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002717
pauleb821182004-05-01 08:44:08 +00002718 if (peer->fd >= 0)
2719 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2720 }
paul718e3742002-12-13 20:15:29 +00002721 }
2722 return 0;
2723}
2724
2725int
2726peer_ebgp_multihop_unset (struct peer *peer)
2727{
2728 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002729 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002730
2731 if (peer_sort (peer) == BGP_PEER_IBGP)
2732 return 0;
2733
Nick Hilliardfa411a22011-03-23 15:33:17 +00002734 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2735 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2736
paul718e3742002-12-13 20:15:29 +00002737 if (peer_group_active (peer))
2738 peer->ttl = peer->group->conf->ttl;
2739 else
2740 peer->ttl = 1;
2741
2742 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2743 {
pauleb821182004-05-01 08:44:08 +00002744 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2745 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002746 }
2747 else
2748 {
2749 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002750 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002751 {
2752 if (peer_sort (peer) == BGP_PEER_IBGP)
2753 continue;
paul718e3742002-12-13 20:15:29 +00002754
pauleb821182004-05-01 08:44:08 +00002755 peer->ttl = 1;
2756
2757 if (peer->fd >= 0)
2758 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2759 }
paul718e3742002-12-13 20:15:29 +00002760 }
2761 return 0;
2762}
2763
2764/* Neighbor description. */
2765int
2766peer_description_set (struct peer *peer, char *desc)
2767{
2768 if (peer->desc)
2769 XFREE (MTYPE_PEER_DESC, peer->desc);
2770
2771 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2772
2773 return 0;
2774}
2775
2776int
2777peer_description_unset (struct peer *peer)
2778{
2779 if (peer->desc)
2780 XFREE (MTYPE_PEER_DESC, peer->desc);
2781
2782 peer->desc = NULL;
2783
2784 return 0;
2785}
2786
2787/* Neighbor update-source. */
2788int
paulfd79ac92004-10-13 05:06:08 +00002789peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002790{
2791 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002792 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002793
2794 if (peer->update_if)
2795 {
2796 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2797 && strcmp (peer->update_if, ifname) == 0)
2798 return 0;
2799
2800 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2801 peer->update_if = NULL;
2802 }
2803
2804 if (peer->update_source)
2805 {
2806 sockunion_free (peer->update_source);
2807 peer->update_source = NULL;
2808 }
2809
2810 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2811
2812 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2813 {
2814 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002815 {
2816 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2817 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2818 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2819 }
paul718e3742002-12-13 20:15:29 +00002820 else
2821 BGP_EVENT_ADD (peer, BGP_Stop);
2822 return 0;
2823 }
2824
2825 /* peer-group member updates. */
2826 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002827 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002828 {
2829 if (peer->update_if)
2830 {
2831 if (strcmp (peer->update_if, ifname) == 0)
2832 continue;
2833
2834 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2835 peer->update_if = NULL;
2836 }
2837
2838 if (peer->update_source)
2839 {
2840 sockunion_free (peer->update_source);
2841 peer->update_source = NULL;
2842 }
2843
2844 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2845
2846 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002847 {
2848 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2849 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2850 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2851 }
paul718e3742002-12-13 20:15:29 +00002852 else
2853 BGP_EVENT_ADD (peer, BGP_Stop);
2854 }
2855 return 0;
2856}
2857
2858int
2859peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2860{
2861 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002862 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002863
2864 if (peer->update_source)
2865 {
2866 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2867 && sockunion_cmp (peer->update_source, su) == 0)
2868 return 0;
2869 sockunion_free (peer->update_source);
2870 peer->update_source = NULL;
2871 }
2872
2873 if (peer->update_if)
2874 {
2875 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2876 peer->update_if = NULL;
2877 }
2878
2879 peer->update_source = sockunion_dup (su);
2880
2881 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2882 {
2883 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002884 {
2885 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2886 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2887 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2888 }
paul718e3742002-12-13 20:15:29 +00002889 else
2890 BGP_EVENT_ADD (peer, BGP_Stop);
2891 return 0;
2892 }
2893
2894 /* peer-group member updates. */
2895 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002896 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002897 {
2898 if (peer->update_source)
2899 {
2900 if (sockunion_cmp (peer->update_source, su) == 0)
2901 continue;
2902 sockunion_free (peer->update_source);
2903 peer->update_source = NULL;
2904 }
2905
2906 if (peer->update_if)
2907 {
2908 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2909 peer->update_if = NULL;
2910 }
2911
2912 peer->update_source = sockunion_dup (su);
2913
2914 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002915 {
2916 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2917 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2918 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2919 }
paul718e3742002-12-13 20:15:29 +00002920 else
2921 BGP_EVENT_ADD (peer, BGP_Stop);
2922 }
2923 return 0;
2924}
2925
2926int
2927peer_update_source_unset (struct peer *peer)
2928{
2929 union sockunion *su;
2930 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002931 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002932
2933 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2934 && ! peer->update_source
2935 && ! peer->update_if)
2936 return 0;
2937
2938 if (peer->update_source)
2939 {
2940 sockunion_free (peer->update_source);
2941 peer->update_source = NULL;
2942 }
2943 if (peer->update_if)
2944 {
2945 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2946 peer->update_if = NULL;
2947 }
2948
2949 if (peer_group_active (peer))
2950 {
2951 group = peer->group;
2952
2953 if (group->conf->update_source)
2954 {
2955 su = sockunion_dup (group->conf->update_source);
2956 peer->update_source = su;
2957 }
2958 else if (group->conf->update_if)
2959 peer->update_if =
2960 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2961 }
2962
2963 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2964 {
2965 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002966 {
2967 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2968 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2969 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2970 }
paul718e3742002-12-13 20:15:29 +00002971 else
2972 BGP_EVENT_ADD (peer, BGP_Stop);
2973 return 0;
2974 }
2975
2976 /* peer-group member updates. */
2977 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002978 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002979 {
2980 if (! peer->update_source && ! peer->update_if)
2981 continue;
2982
2983 if (peer->update_source)
2984 {
2985 sockunion_free (peer->update_source);
2986 peer->update_source = NULL;
2987 }
2988
2989 if (peer->update_if)
2990 {
2991 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2992 peer->update_if = NULL;
2993 }
2994
2995 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002996 {
2997 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2998 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2999 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3000 }
paul718e3742002-12-13 20:15:29 +00003001 else
3002 BGP_EVENT_ADD (peer, BGP_Stop);
3003 }
3004 return 0;
3005}
3006
3007int
3008peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003009 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003010{
3011 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003012 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003013
3014 /* Adress family must be activated. */
3015 if (! peer->afc[afi][safi])
3016 return BGP_ERR_PEER_INACTIVE;
3017
3018 /* Default originate can't be used for peer group memeber. */
3019 if (peer_is_group_member (peer, afi, safi))
3020 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3021
3022 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3023 || (rmap && ! peer->default_rmap[afi][safi].name)
3024 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3025 {
3026 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3027
3028 if (rmap)
3029 {
3030 if (peer->default_rmap[afi][safi].name)
3031 free (peer->default_rmap[afi][safi].name);
3032 peer->default_rmap[afi][safi].name = strdup (rmap);
3033 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3034 }
3035 }
3036
3037 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3038 {
3039 if (peer->status == Established && peer->afc_nego[afi][safi])
3040 bgp_default_originate (peer, afi, safi, 0);
3041 return 0;
3042 }
3043
3044 /* peer-group member updates. */
3045 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003046 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003047 {
3048 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3049
3050 if (rmap)
3051 {
3052 if (peer->default_rmap[afi][safi].name)
3053 free (peer->default_rmap[afi][safi].name);
3054 peer->default_rmap[afi][safi].name = strdup (rmap);
3055 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3056 }
3057
3058 if (peer->status == Established && peer->afc_nego[afi][safi])
3059 bgp_default_originate (peer, afi, safi, 0);
3060 }
3061 return 0;
3062}
3063
3064int
3065peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3066{
3067 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003068 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003069
3070 /* Adress family must be activated. */
3071 if (! peer->afc[afi][safi])
3072 return BGP_ERR_PEER_INACTIVE;
3073
3074 /* Default originate can't be used for peer group memeber. */
3075 if (peer_is_group_member (peer, afi, safi))
3076 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3077
3078 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3079 {
3080 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3081
3082 if (peer->default_rmap[afi][safi].name)
3083 free (peer->default_rmap[afi][safi].name);
3084 peer->default_rmap[afi][safi].name = NULL;
3085 peer->default_rmap[afi][safi].map = NULL;
3086 }
3087
3088 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3089 {
3090 if (peer->status == Established && peer->afc_nego[afi][safi])
3091 bgp_default_originate (peer, afi, safi, 1);
3092 return 0;
3093 }
3094
3095 /* peer-group member updates. */
3096 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003097 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003098 {
3099 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3100
3101 if (peer->default_rmap[afi][safi].name)
3102 free (peer->default_rmap[afi][safi].name);
3103 peer->default_rmap[afi][safi].name = NULL;
3104 peer->default_rmap[afi][safi].map = NULL;
3105
3106 if (peer->status == Established && peer->afc_nego[afi][safi])
3107 bgp_default_originate (peer, afi, safi, 1);
3108 }
3109 return 0;
3110}
3111
3112int
3113peer_port_set (struct peer *peer, u_int16_t port)
3114{
3115 peer->port = port;
3116 return 0;
3117}
3118
3119int
3120peer_port_unset (struct peer *peer)
3121{
3122 peer->port = BGP_PORT_DEFAULT;
3123 return 0;
3124}
3125
3126/* neighbor weight. */
3127int
3128peer_weight_set (struct peer *peer, u_int16_t weight)
3129{
3130 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003131 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003132
3133 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3134 peer->weight = weight;
3135
3136 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3137 return 0;
3138
3139 /* peer-group member updates. */
3140 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003141 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003142 {
3143 peer->weight = group->conf->weight;
3144 }
3145 return 0;
3146}
3147
3148int
3149peer_weight_unset (struct peer *peer)
3150{
3151 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003152 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003153
3154 /* Set default weight. */
3155 if (peer_group_active (peer))
3156 peer->weight = peer->group->conf->weight;
3157 else
3158 peer->weight = 0;
3159
3160 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3161
3162 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3163 return 0;
3164
3165 /* peer-group member updates. */
3166 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003167 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003168 {
3169 peer->weight = 0;
3170 }
3171 return 0;
3172}
3173
3174int
3175peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3176{
3177 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003178 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003179
3180 /* Not for peer group memeber. */
3181 if (peer_group_active (peer))
3182 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3183
3184 /* keepalive value check. */
3185 if (keepalive > 65535)
3186 return BGP_ERR_INVALID_VALUE;
3187
3188 /* Holdtime value check. */
3189 if (holdtime > 65535)
3190 return BGP_ERR_INVALID_VALUE;
3191
3192 /* Holdtime value must be either 0 or greater than 3. */
3193 if (holdtime < 3 && holdtime != 0)
3194 return BGP_ERR_INVALID_VALUE;
3195
3196 /* Set value to the configuration. */
3197 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3198 peer->holdtime = holdtime;
3199 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3200
3201 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3202 return 0;
3203
3204 /* peer-group member updates. */
3205 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003206 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003207 {
3208 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3209 peer->holdtime = group->conf->holdtime;
3210 peer->keepalive = group->conf->keepalive;
3211 }
3212 return 0;
3213}
3214
3215int
3216peer_timers_unset (struct peer *peer)
3217{
3218 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003219 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003220
3221 if (peer_group_active (peer))
3222 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3223
3224 /* Clear configuration. */
3225 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3226 peer->keepalive = 0;
3227 peer->holdtime = 0;
3228
3229 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3230 return 0;
3231
3232 /* peer-group member updates. */
3233 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003234 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003235 {
3236 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3237 peer->holdtime = 0;
3238 peer->keepalive = 0;
3239 }
3240
3241 return 0;
3242}
3243
3244int
3245peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3246{
3247 if (peer_group_active (peer))
3248 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3249
3250 if (connect > 65535)
3251 return BGP_ERR_INVALID_VALUE;
3252
3253 /* Set value to the configuration. */
3254 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3255 peer->connect = connect;
3256
3257 /* Set value to timer setting. */
3258 peer->v_connect = connect;
3259
3260 return 0;
3261}
3262
3263int
3264peer_timers_connect_unset (struct peer *peer)
3265{
3266 if (peer_group_active (peer))
3267 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3268
3269 /* Clear configuration. */
3270 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3271 peer->connect = 0;
3272
3273 /* Set timer setting to default value. */
3274 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3275
3276 return 0;
3277}
3278
3279int
3280peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3281{
3282 if (peer_group_active (peer))
3283 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3284
3285 if (routeadv > 600)
3286 return BGP_ERR_INVALID_VALUE;
3287
3288 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3289 peer->routeadv = routeadv;
3290 peer->v_routeadv = routeadv;
3291
3292 return 0;
3293}
3294
3295int
3296peer_advertise_interval_unset (struct peer *peer)
3297{
3298 if (peer_group_active (peer))
3299 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3300
3301 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3302 peer->routeadv = 0;
3303
3304 if (peer_sort (peer) == BGP_PEER_IBGP)
3305 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3306 else
3307 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3308
3309 return 0;
3310}
3311
paul718e3742002-12-13 20:15:29 +00003312/* neighbor interface */
3313int
paulfd79ac92004-10-13 05:06:08 +00003314peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003315{
3316 if (peer->ifname)
3317 free (peer->ifname);
3318 peer->ifname = strdup (str);
3319
3320 return 0;
3321}
3322
3323int
3324peer_interface_unset (struct peer *peer)
3325{
3326 if (peer->ifname)
3327 free (peer->ifname);
3328 peer->ifname = NULL;
3329
3330 return 0;
3331}
3332
3333/* Allow-as in. */
3334int
3335peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3336{
3337 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003338 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003339
3340 if (allow_num < 1 || allow_num > 10)
3341 return BGP_ERR_INVALID_VALUE;
3342
3343 if (peer->allowas_in[afi][safi] != allow_num)
3344 {
3345 peer->allowas_in[afi][safi] = allow_num;
3346 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3347 peer_change_action (peer, afi, safi, peer_change_reset_in);
3348 }
3349
3350 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3351 return 0;
3352
3353 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003354 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003355 {
3356 if (peer->allowas_in[afi][safi] != allow_num)
3357 {
3358 peer->allowas_in[afi][safi] = allow_num;
3359 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3360 peer_change_action (peer, afi, safi, peer_change_reset_in);
3361 }
3362
3363 }
3364 return 0;
3365}
3366
3367int
3368peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3369{
3370 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003371 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003372
3373 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3374 {
3375 peer->allowas_in[afi][safi] = 0;
3376 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3377 }
3378
3379 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3380 return 0;
3381
3382 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003383 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003384 {
3385 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3386 {
3387 peer->allowas_in[afi][safi] = 0;
3388 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3389 }
3390 }
3391 return 0;
3392}
3393
3394int
3395peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3396{
3397 struct bgp *bgp = peer->bgp;
3398 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003399 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003400
3401 if (peer_sort (peer) != BGP_PEER_EBGP
3402 && peer_sort (peer) != BGP_PEER_INTERNAL)
3403 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3404
3405 if (bgp->as == as)
3406 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3407
3408 if (peer_group_active (peer))
3409 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3410
3411 if (peer->change_local_as == as &&
3412 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3413 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3414 return 0;
3415
3416 peer->change_local_as = as;
3417 if (no_prepend)
3418 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3419 else
3420 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3421
3422 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3423 {
3424 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003425 {
3426 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3427 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3428 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3429 }
paul718e3742002-12-13 20:15:29 +00003430 else
3431 BGP_EVENT_ADD (peer, BGP_Stop);
3432
3433 return 0;
3434 }
3435
3436 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003437 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003438 {
3439 peer->change_local_as = as;
3440 if (no_prepend)
3441 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3442 else
3443 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3444
3445 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003446 {
3447 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3448 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3449 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3450 }
paul718e3742002-12-13 20:15:29 +00003451 else
3452 BGP_EVENT_ADD (peer, BGP_Stop);
3453 }
3454
3455 return 0;
3456}
3457
3458int
3459peer_local_as_unset (struct peer *peer)
3460{
3461 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003462 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003463
3464 if (peer_group_active (peer))
3465 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3466
3467 if (! peer->change_local_as)
3468 return 0;
3469
3470 peer->change_local_as = 0;
3471 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3472
3473 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3474 {
3475 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003476 {
3477 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3478 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3479 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3480 }
paul718e3742002-12-13 20:15:29 +00003481 else
3482 BGP_EVENT_ADD (peer, BGP_Stop);
3483
3484 return 0;
3485 }
3486
3487 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003488 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003489 {
3490 peer->change_local_as = 0;
3491 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3492
3493 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003494 {
3495 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3496 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3497 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3498 }
paul718e3742002-12-13 20:15:29 +00003499 else
3500 BGP_EVENT_ADD (peer, BGP_Stop);
3501 }
3502 return 0;
3503}
3504
Paul Jakma0df7c912008-07-21 21:02:49 +00003505/* Set password for authenticating with the peer. */
3506int
3507peer_password_set (struct peer *peer, const char *password)
3508{
3509 struct listnode *nn, *nnode;
3510 int len = password ? strlen(password) : 0;
3511 int ret = BGP_SUCCESS;
3512
3513 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3514 return BGP_ERR_INVALID_VALUE;
3515
3516 if (peer->password && strcmp (peer->password, password) == 0
3517 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3518 return 0;
3519
3520 if (peer->password)
3521 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3522
3523 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3524
3525 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3526 {
3527 if (peer->status == Established)
3528 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3529 else
3530 BGP_EVENT_ADD (peer, BGP_Stop);
3531
3532 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3533 }
3534
3535 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3536 {
3537 if (peer->password && strcmp (peer->password, password) == 0)
3538 continue;
3539
3540 if (peer->password)
3541 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3542
3543 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3544
3545 if (peer->status == Established)
3546 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3547 else
3548 BGP_EVENT_ADD (peer, BGP_Stop);
3549
3550 if (bgp_md5_set (peer) < 0)
3551 ret = BGP_ERR_TCPSIG_FAILED;
3552 }
3553
3554 return ret;
3555}
3556
3557int
3558peer_password_unset (struct peer *peer)
3559{
3560 struct listnode *nn, *nnode;
3561
3562 if (!peer->password
3563 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3564 return 0;
3565
3566 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3567 {
3568 if (peer_group_active (peer)
3569 && peer->group->conf->password
3570 && strcmp (peer->group->conf->password, peer->password) == 0)
3571 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3572
3573 if (peer->status == Established)
3574 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3575 else
3576 BGP_EVENT_ADD (peer, BGP_Stop);
3577
3578 if (peer->password)
3579 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3580
3581 peer->password = NULL;
3582
3583 bgp_md5_set (peer);
3584
3585 return 0;
3586 }
3587
3588 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3589 peer->password = NULL;
3590
3591 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3592 {
3593 if (!peer->password)
3594 continue;
3595
3596 if (peer->status == Established)
3597 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3598 else
3599 BGP_EVENT_ADD (peer, BGP_Stop);
3600
3601 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3602 peer->password = NULL;
3603
3604 bgp_md5_set (peer);
3605 }
3606
3607 return 0;
3608}
3609
paul718e3742002-12-13 20:15:29 +00003610/* Set distribute list to the peer. */
3611int
3612peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003613 const char *name)
paul718e3742002-12-13 20:15:29 +00003614{
3615 struct bgp_filter *filter;
3616 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003617 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003618
3619 if (! peer->afc[afi][safi])
3620 return BGP_ERR_PEER_INACTIVE;
3621
3622 if (direct != FILTER_IN && direct != FILTER_OUT)
3623 return BGP_ERR_INVALID_VALUE;
3624
3625 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3626 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3627
3628 filter = &peer->filter[afi][safi];
3629
3630 if (filter->plist[direct].name)
3631 return BGP_ERR_PEER_FILTER_CONFLICT;
3632
3633 if (filter->dlist[direct].name)
3634 free (filter->dlist[direct].name);
3635 filter->dlist[direct].name = strdup (name);
3636 filter->dlist[direct].alist = access_list_lookup (afi, name);
3637
3638 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3639 return 0;
3640
3641 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003642 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003643 {
3644 filter = &peer->filter[afi][safi];
3645
3646 if (! peer->af_group[afi][safi])
3647 continue;
3648
3649 if (filter->dlist[direct].name)
3650 free (filter->dlist[direct].name);
3651 filter->dlist[direct].name = strdup (name);
3652 filter->dlist[direct].alist = access_list_lookup (afi, name);
3653 }
3654
3655 return 0;
3656}
3657
3658int
3659peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3660{
3661 struct bgp_filter *filter;
3662 struct bgp_filter *gfilter;
3663 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003664 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003665
3666 if (! peer->afc[afi][safi])
3667 return BGP_ERR_PEER_INACTIVE;
3668
3669 if (direct != FILTER_IN && direct != FILTER_OUT)
3670 return BGP_ERR_INVALID_VALUE;
3671
3672 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3673 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3674
3675 filter = &peer->filter[afi][safi];
3676
3677 /* apply peer-group filter */
3678 if (peer->af_group[afi][safi])
3679 {
3680 gfilter = &peer->group->conf->filter[afi][safi];
3681
3682 if (gfilter->dlist[direct].name)
3683 {
3684 if (filter->dlist[direct].name)
3685 free (filter->dlist[direct].name);
3686 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3687 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3688 return 0;
3689 }
3690 }
3691
3692 if (filter->dlist[direct].name)
3693 free (filter->dlist[direct].name);
3694 filter->dlist[direct].name = NULL;
3695 filter->dlist[direct].alist = NULL;
3696
3697 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3698 return 0;
3699
3700 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003702 {
3703 filter = &peer->filter[afi][safi];
3704
3705 if (! peer->af_group[afi][safi])
3706 continue;
3707
3708 if (filter->dlist[direct].name)
3709 free (filter->dlist[direct].name);
3710 filter->dlist[direct].name = NULL;
3711 filter->dlist[direct].alist = NULL;
3712 }
3713
3714 return 0;
3715}
3716
3717/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003718static void
paul718e3742002-12-13 20:15:29 +00003719peer_distribute_update (struct access_list *access)
3720{
3721 afi_t afi;
3722 safi_t safi;
3723 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003724 struct listnode *mnode, *mnnode;
3725 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003726 struct bgp *bgp;
3727 struct peer *peer;
3728 struct peer_group *group;
3729 struct bgp_filter *filter;
3730
paul1eb8ef22005-04-07 07:30:20 +00003731 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003732 {
paul1eb8ef22005-04-07 07:30:20 +00003733 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003734 {
3735 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3736 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3737 {
3738 filter = &peer->filter[afi][safi];
3739
3740 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3741 {
3742 if (filter->dlist[direct].name)
3743 filter->dlist[direct].alist =
3744 access_list_lookup (afi, filter->dlist[direct].name);
3745 else
3746 filter->dlist[direct].alist = NULL;
3747 }
3748 }
3749 }
paul1eb8ef22005-04-07 07:30:20 +00003750 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003751 {
3752 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3753 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3754 {
3755 filter = &group->conf->filter[afi][safi];
3756
3757 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3758 {
3759 if (filter->dlist[direct].name)
3760 filter->dlist[direct].alist =
3761 access_list_lookup (afi, filter->dlist[direct].name);
3762 else
3763 filter->dlist[direct].alist = NULL;
3764 }
3765 }
3766 }
3767 }
3768}
3769
3770/* Set prefix list to the peer. */
3771int
3772peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003773 const char *name)
paul718e3742002-12-13 20:15:29 +00003774{
3775 struct bgp_filter *filter;
3776 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003778
3779 if (! peer->afc[afi][safi])
3780 return BGP_ERR_PEER_INACTIVE;
3781
3782 if (direct != FILTER_IN && direct != FILTER_OUT)
3783 return BGP_ERR_INVALID_VALUE;
3784
3785 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3786 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3787
3788 filter = &peer->filter[afi][safi];
3789
3790 if (filter->dlist[direct].name)
3791 return BGP_ERR_PEER_FILTER_CONFLICT;
3792
3793 if (filter->plist[direct].name)
3794 free (filter->plist[direct].name);
3795 filter->plist[direct].name = strdup (name);
3796 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3797
3798 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3799 return 0;
3800
3801 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003802 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003803 {
3804 filter = &peer->filter[afi][safi];
3805
3806 if (! peer->af_group[afi][safi])
3807 continue;
3808
3809 if (filter->plist[direct].name)
3810 free (filter->plist[direct].name);
3811 filter->plist[direct].name = strdup (name);
3812 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3813 }
3814 return 0;
3815}
3816
3817int
3818peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3819{
3820 struct bgp_filter *filter;
3821 struct bgp_filter *gfilter;
3822 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003823 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003824
3825 if (! peer->afc[afi][safi])
3826 return BGP_ERR_PEER_INACTIVE;
3827
3828 if (direct != FILTER_IN && direct != FILTER_OUT)
3829 return BGP_ERR_INVALID_VALUE;
3830
3831 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3832 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3833
3834 filter = &peer->filter[afi][safi];
3835
3836 /* apply peer-group filter */
3837 if (peer->af_group[afi][safi])
3838 {
3839 gfilter = &peer->group->conf->filter[afi][safi];
3840
3841 if (gfilter->plist[direct].name)
3842 {
3843 if (filter->plist[direct].name)
3844 free (filter->plist[direct].name);
3845 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3846 filter->plist[direct].plist = gfilter->plist[direct].plist;
3847 return 0;
3848 }
3849 }
3850
3851 if (filter->plist[direct].name)
3852 free (filter->plist[direct].name);
3853 filter->plist[direct].name = NULL;
3854 filter->plist[direct].plist = NULL;
3855
3856 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3857 return 0;
3858
3859 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003860 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003861 {
3862 filter = &peer->filter[afi][safi];
3863
3864 if (! peer->af_group[afi][safi])
3865 continue;
3866
3867 if (filter->plist[direct].name)
3868 free (filter->plist[direct].name);
3869 filter->plist[direct].name = NULL;
3870 filter->plist[direct].plist = NULL;
3871 }
3872
3873 return 0;
3874}
3875
3876/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003877static void
paul718e3742002-12-13 20:15:29 +00003878peer_prefix_list_update (struct prefix_list *plist)
3879{
paul1eb8ef22005-04-07 07:30:20 +00003880 struct listnode *mnode, *mnnode;
3881 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003882 struct bgp *bgp;
3883 struct peer *peer;
3884 struct peer_group *group;
3885 struct bgp_filter *filter;
3886 afi_t afi;
3887 safi_t safi;
3888 int direct;
3889
paul1eb8ef22005-04-07 07:30:20 +00003890 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003891 {
paul1eb8ef22005-04-07 07:30:20 +00003892 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003893 {
3894 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3895 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3896 {
3897 filter = &peer->filter[afi][safi];
3898
3899 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3900 {
3901 if (filter->plist[direct].name)
3902 filter->plist[direct].plist =
3903 prefix_list_lookup (afi, filter->plist[direct].name);
3904 else
3905 filter->plist[direct].plist = NULL;
3906 }
3907 }
3908 }
paul1eb8ef22005-04-07 07:30:20 +00003909 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003910 {
3911 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3912 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3913 {
3914 filter = &group->conf->filter[afi][safi];
3915
3916 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3917 {
3918 if (filter->plist[direct].name)
3919 filter->plist[direct].plist =
3920 prefix_list_lookup (afi, filter->plist[direct].name);
3921 else
3922 filter->plist[direct].plist = NULL;
3923 }
3924 }
3925 }
3926 }
3927}
3928
3929int
3930peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003931 const char *name)
paul718e3742002-12-13 20:15:29 +00003932{
3933 struct bgp_filter *filter;
3934 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003935 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003936
3937 if (! peer->afc[afi][safi])
3938 return BGP_ERR_PEER_INACTIVE;
3939
3940 if (direct != FILTER_IN && direct != FILTER_OUT)
3941 return BGP_ERR_INVALID_VALUE;
3942
3943 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3944 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3945
3946 filter = &peer->filter[afi][safi];
3947
3948 if (filter->aslist[direct].name)
3949 free (filter->aslist[direct].name);
3950 filter->aslist[direct].name = strdup (name);
3951 filter->aslist[direct].aslist = as_list_lookup (name);
3952
3953 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3954 return 0;
3955
3956 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003957 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003958 {
3959 filter = &peer->filter[afi][safi];
3960
3961 if (! peer->af_group[afi][safi])
3962 continue;
3963
3964 if (filter->aslist[direct].name)
3965 free (filter->aslist[direct].name);
3966 filter->aslist[direct].name = strdup (name);
3967 filter->aslist[direct].aslist = as_list_lookup (name);
3968 }
3969 return 0;
3970}
3971
3972int
3973peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3974{
3975 struct bgp_filter *filter;
3976 struct bgp_filter *gfilter;
3977 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003978 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003979
3980 if (! peer->afc[afi][safi])
3981 return BGP_ERR_PEER_INACTIVE;
3982
hassob5f29602005-05-25 21:00:28 +00003983 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003984 return BGP_ERR_INVALID_VALUE;
3985
hassob5f29602005-05-25 21:00:28 +00003986 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003987 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3988
3989 filter = &peer->filter[afi][safi];
3990
3991 /* apply peer-group filter */
3992 if (peer->af_group[afi][safi])
3993 {
3994 gfilter = &peer->group->conf->filter[afi][safi];
3995
3996 if (gfilter->aslist[direct].name)
3997 {
3998 if (filter->aslist[direct].name)
3999 free (filter->aslist[direct].name);
4000 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4001 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4002 return 0;
4003 }
4004 }
4005
4006 if (filter->aslist[direct].name)
4007 free (filter->aslist[direct].name);
4008 filter->aslist[direct].name = NULL;
4009 filter->aslist[direct].aslist = NULL;
4010
4011 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4012 return 0;
4013
4014 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004015 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004016 {
4017 filter = &peer->filter[afi][safi];
4018
4019 if (! peer->af_group[afi][safi])
4020 continue;
4021
4022 if (filter->aslist[direct].name)
4023 free (filter->aslist[direct].name);
4024 filter->aslist[direct].name = NULL;
4025 filter->aslist[direct].aslist = NULL;
4026 }
4027
4028 return 0;
4029}
4030
paul94f2b392005-06-28 12:44:16 +00004031static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004032peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004033{
4034 afi_t afi;
4035 safi_t safi;
4036 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004037 struct listnode *mnode, *mnnode;
4038 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004039 struct bgp *bgp;
4040 struct peer *peer;
4041 struct peer_group *group;
4042 struct bgp_filter *filter;
4043
paul1eb8ef22005-04-07 07:30:20 +00004044 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004045 {
paul1eb8ef22005-04-07 07:30:20 +00004046 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004047 {
4048 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4049 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4050 {
4051 filter = &peer->filter[afi][safi];
4052
4053 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4054 {
4055 if (filter->aslist[direct].name)
4056 filter->aslist[direct].aslist =
4057 as_list_lookup (filter->aslist[direct].name);
4058 else
4059 filter->aslist[direct].aslist = NULL;
4060 }
4061 }
4062 }
paul1eb8ef22005-04-07 07:30:20 +00004063 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004064 {
4065 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4066 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4067 {
4068 filter = &group->conf->filter[afi][safi];
4069
4070 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4071 {
4072 if (filter->aslist[direct].name)
4073 filter->aslist[direct].aslist =
4074 as_list_lookup (filter->aslist[direct].name);
4075 else
4076 filter->aslist[direct].aslist = NULL;
4077 }
4078 }
4079 }
4080 }
4081}
4082
4083/* Set route-map to the peer. */
4084int
4085peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004086 const char *name)
paul718e3742002-12-13 20:15:29 +00004087{
4088 struct bgp_filter *filter;
4089 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004090 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004091
4092 if (! peer->afc[afi][safi])
4093 return BGP_ERR_PEER_INACTIVE;
4094
paulfee0f4c2004-09-13 05:12:46 +00004095 if (direct != RMAP_IN && direct != RMAP_OUT &&
4096 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004097 return BGP_ERR_INVALID_VALUE;
4098
paulfee0f4c2004-09-13 05:12:46 +00004099 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4100 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004101 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4102
4103 filter = &peer->filter[afi][safi];
4104
4105 if (filter->map[direct].name)
4106 free (filter->map[direct].name);
4107
4108 filter->map[direct].name = strdup (name);
4109 filter->map[direct].map = route_map_lookup_by_name (name);
4110
4111 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4112 return 0;
4113
4114 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004115 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004116 {
4117 filter = &peer->filter[afi][safi];
4118
4119 if (! peer->af_group[afi][safi])
4120 continue;
4121
4122 if (filter->map[direct].name)
4123 free (filter->map[direct].name);
4124 filter->map[direct].name = strdup (name);
4125 filter->map[direct].map = route_map_lookup_by_name (name);
4126 }
4127 return 0;
4128}
4129
4130/* Unset route-map from the peer. */
4131int
4132peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4133{
4134 struct bgp_filter *filter;
4135 struct bgp_filter *gfilter;
4136 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004137 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004138
4139 if (! peer->afc[afi][safi])
4140 return BGP_ERR_PEER_INACTIVE;
4141
hassob5f29602005-05-25 21:00:28 +00004142 if (direct != RMAP_IN && direct != RMAP_OUT &&
4143 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004144 return BGP_ERR_INVALID_VALUE;
4145
hassob5f29602005-05-25 21:00:28 +00004146 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4147 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004148 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4149
4150 filter = &peer->filter[afi][safi];
4151
4152 /* apply peer-group filter */
4153 if (peer->af_group[afi][safi])
4154 {
4155 gfilter = &peer->group->conf->filter[afi][safi];
4156
4157 if (gfilter->map[direct].name)
4158 {
4159 if (filter->map[direct].name)
4160 free (filter->map[direct].name);
4161 filter->map[direct].name = strdup (gfilter->map[direct].name);
4162 filter->map[direct].map = gfilter->map[direct].map;
4163 return 0;
4164 }
4165 }
4166
4167 if (filter->map[direct].name)
4168 free (filter->map[direct].name);
4169 filter->map[direct].name = NULL;
4170 filter->map[direct].map = NULL;
4171
4172 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4173 return 0;
4174
4175 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004176 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004177 {
4178 filter = &peer->filter[afi][safi];
4179
4180 if (! peer->af_group[afi][safi])
4181 continue;
4182
4183 if (filter->map[direct].name)
4184 free (filter->map[direct].name);
4185 filter->map[direct].name = NULL;
4186 filter->map[direct].map = NULL;
4187 }
4188 return 0;
4189}
4190
4191/* Set unsuppress-map to the peer. */
4192int
paulfd79ac92004-10-13 05:06:08 +00004193peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4194 const char *name)
paul718e3742002-12-13 20:15:29 +00004195{
4196 struct bgp_filter *filter;
4197 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004198 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004199
4200 if (! peer->afc[afi][safi])
4201 return BGP_ERR_PEER_INACTIVE;
4202
4203 if (peer_is_group_member (peer, afi, safi))
4204 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4205
4206 filter = &peer->filter[afi][safi];
4207
4208 if (filter->usmap.name)
4209 free (filter->usmap.name);
4210
4211 filter->usmap.name = strdup (name);
4212 filter->usmap.map = route_map_lookup_by_name (name);
4213
4214 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4215 return 0;
4216
4217 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004218 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004219 {
4220 filter = &peer->filter[afi][safi];
4221
4222 if (! peer->af_group[afi][safi])
4223 continue;
4224
4225 if (filter->usmap.name)
4226 free (filter->usmap.name);
4227 filter->usmap.name = strdup (name);
4228 filter->usmap.map = route_map_lookup_by_name (name);
4229 }
4230 return 0;
4231}
4232
4233/* Unset route-map from the peer. */
4234int
4235peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4236{
4237 struct bgp_filter *filter;
4238 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004239 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004240
4241 if (! peer->afc[afi][safi])
4242 return BGP_ERR_PEER_INACTIVE;
4243
4244 if (peer_is_group_member (peer, afi, safi))
4245 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4246
4247 filter = &peer->filter[afi][safi];
4248
4249 if (filter->usmap.name)
4250 free (filter->usmap.name);
4251 filter->usmap.name = NULL;
4252 filter->usmap.map = NULL;
4253
4254 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4255 return 0;
4256
4257 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004258 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004259 {
4260 filter = &peer->filter[afi][safi];
4261
4262 if (! peer->af_group[afi][safi])
4263 continue;
4264
4265 if (filter->usmap.name)
4266 free (filter->usmap.name);
4267 filter->usmap.name = NULL;
4268 filter->usmap.map = NULL;
4269 }
4270 return 0;
4271}
4272
4273int
4274peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004275 u_int32_t max, u_char threshold,
4276 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004277{
4278 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004279 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004280
4281 if (! peer->afc[afi][safi])
4282 return BGP_ERR_PEER_INACTIVE;
4283
4284 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4285 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004286 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004287 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004288 if (warning)
4289 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4290 else
4291 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4292
4293 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4294 return 0;
4295
4296 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004297 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004298 {
4299 if (! peer->af_group[afi][safi])
4300 continue;
4301
4302 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4303 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004304 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004305 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004306 if (warning)
4307 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4308 else
4309 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4310 }
4311 return 0;
4312}
4313
4314int
4315peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4316{
4317 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004318 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004319
4320 if (! peer->afc[afi][safi])
4321 return BGP_ERR_PEER_INACTIVE;
4322
4323 /* apply peer-group config */
4324 if (peer->af_group[afi][safi])
4325 {
4326 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4327 PEER_FLAG_MAX_PREFIX))
4328 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4329 else
4330 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4331
4332 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4333 PEER_FLAG_MAX_PREFIX_WARNING))
4334 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4335 else
4336 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4337
4338 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004339 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004340 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004341 return 0;
4342 }
4343
4344 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4345 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4346 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004347 peer->pmax_threshold[afi][safi] = 0;
4348 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004349
4350 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4351 return 0;
4352
4353 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004354 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004355 {
4356 if (! peer->af_group[afi][safi])
4357 continue;
4358
4359 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4360 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4361 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004362 peer->pmax_threshold[afi][safi] = 0;
4363 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004364 }
4365 return 0;
4366}
4367
Nick Hilliardfa411a22011-03-23 15:33:17 +00004368/* Set # of hops between us and BGP peer. */
4369int
4370peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4371{
4372 struct peer_group *group;
4373 struct listnode *node, *nnode;
4374 struct peer *peer1;
4375 int ret;
4376
4377 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4378
4379 if (peer_sort (peer) == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004380 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004381
4382 /* We cannot configure ttl-security hops when ebgp-multihop is already
4383 set. For non peer-groups, the check is simple. For peer-groups, it's
4384 slightly messy, because we need to check both the peer-group structure
4385 and all peer-group members for any trace of ebgp-multihop configuration
4386 before actually applying the ttl-security rules. Cisco really made a
4387 mess of this configuration parameter, and OpenBGPD got it right.
4388 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004389
4390 if (peer->gtsm_hops == 0) {
4391 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4392 {
4393 group = peer->group;
4394 if (group->conf->ttl != 1)
4395 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004396
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004397 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4398 {
4399 if (peer_sort (peer1) == BGP_PEER_IBGP)
4400 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004401
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004402 if (peer1->ttl != 1)
4403 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4404 }
4405 }
4406 else
4407 {
4408 if (peer->ttl != 1)
4409 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4410 }
4411 /* specify MAXTTL on outgoing packets */
4412 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4413 if (ret != 0)
4414 return ret;
4415 }
4416
Nick Hilliardfa411a22011-03-23 15:33:17 +00004417 peer->gtsm_hops = gtsm_hops;
4418
Nick Hilliardfa411a22011-03-23 15:33:17 +00004419 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4420 {
4421 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4422 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4423 }
4424 else
4425 {
4426 group = peer->group;
4427 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4428 {
4429 if (peer_sort (peer) == BGP_PEER_IBGP)
4430 continue;
4431
4432 peer->gtsm_hops = group->conf->gtsm_hops;
4433
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004434 /* Change setting of existing peer
4435 * established then change value (may break connectivity)
4436 * not established yet (teardown session and restart)
4437 * no session then do nothing (will get handled by next connection)
4438 */
4439 if (peer->status == Established)
4440 {
4441 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4442 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4443 MAXTTL + 1 - peer->gtsm_hops);
4444 }
4445 else if (peer->status < Established)
4446 {
4447 if (BGP_DEBUG (events, EVENTS))
4448 zlog_debug ("%s Min-ttl changed", peer->host);
4449 BGP_EVENT_ADD (peer, BGP_Stop);
4450 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004451 }
4452 }
4453
4454 return 0;
4455}
4456
4457int
4458peer_ttl_security_hops_unset (struct peer *peer)
4459{
4460 struct peer_group *group;
4461 struct listnode *node, *nnode;
4462 struct peer *opeer;
4463
4464 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4465
4466 if (peer_sort (peer) == BGP_PEER_IBGP)
4467 return 0;
4468
4469 /* if a peer-group member, then reset to peer-group default rather than 0 */
4470 if (peer_group_active (peer))
4471 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4472 else
4473 peer->gtsm_hops = 0;
4474
4475 opeer = peer;
4476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4477 {
4478 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4479 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4480 }
4481 else
4482 {
4483 group = peer->group;
4484 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4485 {
4486 if (peer_sort (peer) == BGP_PEER_IBGP)
4487 continue;
4488
4489 peer->gtsm_hops = 0;
4490
4491 if (peer->fd >= 0)
4492 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4493 }
4494 }
4495
4496 return peer_ebgp_multihop_unset (opeer);
4497}
4498
paul718e3742002-12-13 20:15:29 +00004499int
4500peer_clear (struct peer *peer)
4501{
4502 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4503 {
hasso0a486e52005-02-01 20:57:17 +00004504 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4505 {
4506 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4507 if (peer->t_pmax_restart)
4508 {
4509 BGP_TIMER_OFF (peer->t_pmax_restart);
4510 if (BGP_DEBUG (events, EVENTS))
4511 zlog_debug ("%s Maximum-prefix restart timer canceled",
4512 peer->host);
4513 }
4514 BGP_EVENT_ADD (peer, BGP_Start);
4515 return 0;
4516 }
4517
paul718e3742002-12-13 20:15:29 +00004518 peer->v_start = BGP_INIT_START_TIMER;
4519 if (peer->status == Established)
4520 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4521 BGP_NOTIFY_CEASE_ADMIN_RESET);
4522 else
4523 BGP_EVENT_ADD (peer, BGP_Stop);
4524 }
4525 return 0;
4526}
4527
4528int
4529peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4530 enum bgp_clear_type stype)
4531{
4532 if (peer->status != Established)
4533 return 0;
4534
4535 if (! peer->afc[afi][safi])
4536 return BGP_ERR_AF_UNCONFIGURED;
4537
paulfee0f4c2004-09-13 05:12:46 +00004538 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4539 {
4540 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4541 return 0;
4542 bgp_check_local_routes_rsclient (peer, afi, safi);
4543 bgp_soft_reconfig_rsclient (peer, afi, safi);
4544 }
4545
paul718e3742002-12-13 20:15:29 +00004546 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4547 bgp_announce_route (peer, afi, safi);
4548
4549 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4550 {
4551 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4552 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4553 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4554 {
4555 struct bgp_filter *filter = &peer->filter[afi][safi];
4556 u_char prefix_type;
4557
4558 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4559 prefix_type = ORF_TYPE_PREFIX;
4560 else
4561 prefix_type = ORF_TYPE_PREFIX_OLD;
4562
4563 if (filter->plist[FILTER_IN].plist)
4564 {
4565 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4566 bgp_route_refresh_send (peer, afi, safi,
4567 prefix_type, REFRESH_DEFER, 1);
4568 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4569 REFRESH_IMMEDIATE, 0);
4570 }
4571 else
4572 {
4573 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4574 bgp_route_refresh_send (peer, afi, safi,
4575 prefix_type, REFRESH_IMMEDIATE, 1);
4576 else
4577 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4578 }
4579 return 0;
4580 }
4581 }
4582
4583 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4584 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4585 {
4586 /* If neighbor has soft reconfiguration inbound flag.
4587 Use Adj-RIB-In database. */
4588 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4589 bgp_soft_reconfig_in (peer, afi, safi);
4590 else
4591 {
4592 /* If neighbor has route refresh capability, send route refresh
4593 message to the peer. */
4594 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4595 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4596 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4597 else
4598 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4599 }
4600 }
4601 return 0;
4602}
4603
paulfd79ac92004-10-13 05:06:08 +00004604/* Display peer uptime.*/
4605/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004606char *
4607peer_uptime (time_t uptime2, char *buf, size_t len)
4608{
4609 time_t uptime1;
4610 struct tm *tm;
4611
4612 /* Check buffer length. */
4613 if (len < BGP_UPTIME_LEN)
4614 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004615 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004616 /* XXX: should return status instead of buf... */
4617 snprintf (buf, len, "<error> ");
4618 return buf;
paul718e3742002-12-13 20:15:29 +00004619 }
4620
4621 /* If there is no connection has been done before print `never'. */
4622 if (uptime2 == 0)
4623 {
4624 snprintf (buf, len, "never ");
4625 return buf;
4626 }
4627
4628 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004629 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004630 uptime1 -= uptime2;
4631 tm = gmtime (&uptime1);
4632
4633 /* Making formatted timer strings. */
4634#define ONE_DAY_SECOND 60*60*24
4635#define ONE_WEEK_SECOND 60*60*24*7
4636
4637 if (uptime1 < ONE_DAY_SECOND)
4638 snprintf (buf, len, "%02d:%02d:%02d",
4639 tm->tm_hour, tm->tm_min, tm->tm_sec);
4640 else if (uptime1 < ONE_WEEK_SECOND)
4641 snprintf (buf, len, "%dd%02dh%02dm",
4642 tm->tm_yday, tm->tm_hour, tm->tm_min);
4643 else
4644 snprintf (buf, len, "%02dw%dd%02dh",
4645 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4646 return buf;
4647}
4648
paul94f2b392005-06-28 12:44:16 +00004649static void
paul718e3742002-12-13 20:15:29 +00004650bgp_config_write_filter (struct vty *vty, struct peer *peer,
4651 afi_t afi, safi_t safi)
4652{
4653 struct bgp_filter *filter;
4654 struct bgp_filter *gfilter = NULL;
4655 char *addr;
4656 int in = FILTER_IN;
4657 int out = FILTER_OUT;
4658
4659 addr = peer->host;
4660 filter = &peer->filter[afi][safi];
4661 if (peer->af_group[afi][safi])
4662 gfilter = &peer->group->conf->filter[afi][safi];
4663
4664 /* distribute-list. */
4665 if (filter->dlist[in].name)
4666 if (! gfilter || ! gfilter->dlist[in].name
4667 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4668 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4669 filter->dlist[in].name, VTY_NEWLINE);
4670 if (filter->dlist[out].name && ! gfilter)
4671 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4672 filter->dlist[out].name, VTY_NEWLINE);
4673
4674 /* prefix-list. */
4675 if (filter->plist[in].name)
4676 if (! gfilter || ! gfilter->plist[in].name
4677 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4678 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4679 filter->plist[in].name, VTY_NEWLINE);
4680 if (filter->plist[out].name && ! gfilter)
4681 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4682 filter->plist[out].name, VTY_NEWLINE);
4683
4684 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004685 if (filter->map[RMAP_IN].name)
4686 if (! gfilter || ! gfilter->map[RMAP_IN].name
4687 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004688 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004689 filter->map[RMAP_IN].name, VTY_NEWLINE);
4690 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004691 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004692 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4693 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4694 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4695 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4696 if (filter->map[RMAP_EXPORT].name)
4697 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4698 || strcmp (filter->map[RMAP_EXPORT].name,
4699 gfilter->map[RMAP_EXPORT].name) != 0)
4700 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4701 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004702
4703 /* unsuppress-map */
4704 if (filter->usmap.name && ! gfilter)
4705 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4706 filter->usmap.name, VTY_NEWLINE);
4707
4708 /* filter-list. */
4709 if (filter->aslist[in].name)
4710 if (! gfilter || ! gfilter->aslist[in].name
4711 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4712 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4713 filter->aslist[in].name, VTY_NEWLINE);
4714 if (filter->aslist[out].name && ! gfilter)
4715 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4716 filter->aslist[out].name, VTY_NEWLINE);
4717}
4718
4719/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004720static void
paul718e3742002-12-13 20:15:29 +00004721bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4722 struct peer *peer, afi_t afi, safi_t safi)
4723{
paul718e3742002-12-13 20:15:29 +00004724 struct peer *g_peer = NULL;
4725 char buf[SU_ADDRSTRLEN];
4726 char *addr;
4727
paul718e3742002-12-13 20:15:29 +00004728 addr = peer->host;
4729 if (peer_group_active (peer))
4730 g_peer = peer->group->conf;
4731
4732 /************************************
4733 ****** Global to the neighbor ******
4734 ************************************/
4735 if (afi == AFI_IP && safi == SAFI_UNICAST)
4736 {
4737 /* remote-as. */
4738 if (! peer_group_active (peer))
4739 {
4740 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4741 vty_out (vty, " neighbor %s peer-group%s", addr,
4742 VTY_NEWLINE);
4743 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004744 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004745 VTY_NEWLINE);
4746 }
4747 else
4748 {
4749 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004750 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004751 VTY_NEWLINE);
4752 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4753 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4754 peer->group->name, VTY_NEWLINE);
4755 }
4756
4757 /* local-as. */
4758 if (peer->change_local_as)
4759 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004760 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004761 peer->change_local_as,
4762 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4763 " no-prepend" : "", VTY_NEWLINE);
4764
4765 /* Description. */
4766 if (peer->desc)
4767 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4768 VTY_NEWLINE);
4769
4770 /* Shutdown. */
4771 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4772 if (! peer_group_active (peer) ||
4773 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4774 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4775
Paul Jakma0df7c912008-07-21 21:02:49 +00004776 /* Password. */
4777 if (peer->password)
4778 if (!peer_group_active (peer)
4779 || ! g_peer->password
4780 || strcmp (peer->password, g_peer->password) != 0)
4781 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4782 VTY_NEWLINE);
4783
paul718e3742002-12-13 20:15:29 +00004784 /* BGP port. */
4785 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004786 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004787 VTY_NEWLINE);
4788
4789 /* Local interface name. */
4790 if (peer->ifname)
4791 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4792 VTY_NEWLINE);
4793
4794 /* Passive. */
4795 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4796 if (! peer_group_active (peer) ||
4797 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4798 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4799
4800 /* EBGP multihop. */
Nick Hilliardfa411a22011-03-23 15:33:17 +00004801 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
4802 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004803 if (! peer_group_active (peer) ||
4804 g_peer->ttl != peer->ttl)
4805 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4806 VTY_NEWLINE);
4807
Nick Hilliardfa411a22011-03-23 15:33:17 +00004808 /* ttl-security hops */
4809 if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
4810 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004811 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004812 peer->gtsm_hops, VTY_NEWLINE);
4813
hasso6ffd2072005-02-02 14:50:11 +00004814 /* disable-connected-check. */
4815 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004816 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004817 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4818 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004819
4820 /* Update-source. */
4821 if (peer->update_if)
4822 if (! peer_group_active (peer) || ! g_peer->update_if
4823 || strcmp (g_peer->update_if, peer->update_if) != 0)
4824 vty_out (vty, " neighbor %s update-source %s%s", addr,
4825 peer->update_if, VTY_NEWLINE);
4826 if (peer->update_source)
4827 if (! peer_group_active (peer) || ! g_peer->update_source
4828 || sockunion_cmp (g_peer->update_source,
4829 peer->update_source) != 0)
4830 vty_out (vty, " neighbor %s update-source %s%s", addr,
4831 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4832 VTY_NEWLINE);
4833
paul718e3742002-12-13 20:15:29 +00004834 /* advertisement-interval */
4835 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4836 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4837 addr, peer->v_routeadv, VTY_NEWLINE);
4838
4839 /* timers. */
4840 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4841 && ! peer_group_active (peer))
4842 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4843 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4844
4845 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4846 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4847 peer->connect, VTY_NEWLINE);
4848
4849 /* Default weight. */
4850 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4851 if (! peer_group_active (peer) ||
4852 g_peer->weight != peer->weight)
4853 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4854 VTY_NEWLINE);
4855
paul718e3742002-12-13 20:15:29 +00004856 /* Dynamic capability. */
4857 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4858 if (! peer_group_active (peer) ||
4859 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4860 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4861 VTY_NEWLINE);
4862
4863 /* dont capability negotiation. */
4864 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4865 if (! peer_group_active (peer) ||
4866 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4867 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4868 VTY_NEWLINE);
4869
4870 /* override capability negotiation. */
4871 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4872 if (! peer_group_active (peer) ||
4873 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4874 vty_out (vty, " neighbor %s override-capability%s", addr,
4875 VTY_NEWLINE);
4876
4877 /* strict capability negotiation. */
4878 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4879 if (! peer_group_active (peer) ||
4880 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4881 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4882 VTY_NEWLINE);
4883
4884 if (! peer_group_active (peer))
4885 {
4886 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4887 {
4888 if (peer->afc[AFI_IP][SAFI_UNICAST])
4889 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4890 }
4891 else
4892 {
4893 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4894 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4895 }
4896 }
4897 }
4898
4899
4900 /************************************
4901 ****** Per AF to the neighbor ******
4902 ************************************/
4903
4904 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4905 {
4906 if (peer->af_group[afi][safi])
4907 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4908 peer->group->name, VTY_NEWLINE);
4909 else
4910 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4911 }
4912
4913 /* ORF capability. */
4914 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4915 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4916 if (! peer->af_group[afi][safi])
4917 {
4918 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4919
4920 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4921 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4922 vty_out (vty, " both");
4923 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4924 vty_out (vty, " send");
4925 else
4926 vty_out (vty, " receive");
4927 vty_out (vty, "%s", VTY_NEWLINE);
4928 }
4929
4930 /* Route reflector client. */
4931 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4932 && ! peer->af_group[afi][safi])
4933 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4934 VTY_NEWLINE);
4935
4936 /* Nexthop self. */
4937 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4938 && ! peer->af_group[afi][safi])
4939 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4940
4941 /* Remove private AS. */
4942 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4943 && ! peer->af_group[afi][safi])
4944 vty_out (vty, " neighbor %s remove-private-AS%s",
4945 addr, VTY_NEWLINE);
4946
4947 /* send-community print. */
4948 if (! peer->af_group[afi][safi])
4949 {
4950 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4951 {
4952 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4953 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4954 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4955 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4956 vty_out (vty, " neighbor %s send-community extended%s",
4957 addr, VTY_NEWLINE);
4958 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4959 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4960 }
4961 else
4962 {
4963 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4964 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4965 vty_out (vty, " no neighbor %s send-community both%s",
4966 addr, VTY_NEWLINE);
4967 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4968 vty_out (vty, " no neighbor %s send-community extended%s",
4969 addr, VTY_NEWLINE);
4970 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4971 vty_out (vty, " no neighbor %s send-community%s",
4972 addr, VTY_NEWLINE);
4973 }
4974 }
4975
4976 /* Default information */
4977 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4978 && ! peer->af_group[afi][safi])
4979 {
4980 vty_out (vty, " neighbor %s default-originate", addr);
4981 if (peer->default_rmap[afi][safi].name)
4982 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4983 vty_out (vty, "%s", VTY_NEWLINE);
4984 }
4985
4986 /* Soft reconfiguration inbound. */
4987 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4988 if (! peer->af_group[afi][safi] ||
4989 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4990 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4991 VTY_NEWLINE);
4992
4993 /* maximum-prefix. */
4994 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4995 if (! peer->af_group[afi][safi]
4996 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004997 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004998 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4999 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005000 {
hasso0a486e52005-02-01 20:57:17 +00005001 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5002 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5003 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5004 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5005 vty_out (vty, " warning-only");
5006 if (peer->pmax_restart[afi][safi])
5007 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5008 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005009 }
paul718e3742002-12-13 20:15:29 +00005010
5011 /* Route server client. */
5012 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5013 && ! peer->af_group[afi][safi])
5014 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5015
Dylan Hall3cf12882011-10-27 15:28:17 +04005016 /* Nexthop-local unchanged. */
5017 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5018 && ! peer->af_group[afi][safi])
5019 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5020
paul718e3742002-12-13 20:15:29 +00005021 /* Allow AS in. */
5022 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5023 if (! peer_group_active (peer)
5024 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5025 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5026 {
5027 if (peer->allowas_in[afi][safi] == 3)
5028 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5029 else
5030 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5031 peer->allowas_in[afi][safi], VTY_NEWLINE);
5032 }
5033
5034 /* Filter. */
5035 bgp_config_write_filter (vty, peer, afi, safi);
5036
5037 /* atribute-unchanged. */
5038 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5039 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5040 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5041 && ! peer->af_group[afi][safi])
5042 {
5043 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5044 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5045 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5046 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5047 else
5048 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5049 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5050 " as-path" : "",
5051 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5052 " next-hop" : "",
5053 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5054 " med" : "", VTY_NEWLINE);
5055 }
5056}
5057
5058/* Display "address-family" configuration header. */
5059void
5060bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5061 int *write)
5062{
5063 if (*write)
5064 return;
5065
5066 if (afi == AFI_IP && safi == SAFI_UNICAST)
5067 return;
5068
5069 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5070
5071 if (afi == AFI_IP)
5072 {
5073 if (safi == SAFI_MULTICAST)
5074 vty_out (vty, "ipv4 multicast");
5075 else if (safi == SAFI_MPLS_VPN)
5076 vty_out (vty, "vpnv4 unicast");
5077 }
5078 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005079 {
5080 vty_out (vty, "ipv6");
5081
5082 if (safi == SAFI_MULTICAST)
5083 vty_out (vty, " multicast");
5084 }
paul718e3742002-12-13 20:15:29 +00005085
5086 vty_out (vty, "%s", VTY_NEWLINE);
5087
5088 *write = 1;
5089}
5090
5091/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005092static int
paul718e3742002-12-13 20:15:29 +00005093bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5094 safi_t safi)
5095{
5096 int write = 0;
5097 struct peer *peer;
5098 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005099 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005100
5101 bgp_config_write_network (vty, bgp, afi, safi, &write);
5102
5103 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5104
paul1eb8ef22005-04-07 07:30:20 +00005105 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005106 {
5107 if (group->conf->afc[afi][safi])
5108 {
5109 bgp_config_write_family_header (vty, afi, safi, &write);
5110 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5111 }
5112 }
paul1eb8ef22005-04-07 07:30:20 +00005113 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005114 {
5115 if (peer->afc[afi][safi])
5116 {
5117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5118 {
5119 bgp_config_write_family_header (vty, afi, safi, &write);
5120 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5121 }
5122 }
5123 }
5124 if (write)
5125 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5126
5127 return write;
5128}
5129
5130int
5131bgp_config_write (struct vty *vty)
5132{
5133 int write = 0;
5134 struct bgp *bgp;
5135 struct peer_group *group;
5136 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005137 struct listnode *node, *nnode;
5138 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005139
5140 /* BGP Multiple instance. */
5141 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5142 {
5143 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5144 write++;
5145 }
5146
5147 /* BGP Config type. */
5148 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5149 {
5150 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5151 write++;
5152 }
5153
5154 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005155 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005156 {
5157 if (write)
5158 vty_out (vty, "!%s", VTY_NEWLINE);
5159
5160 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005161 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005162
5163 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5164 {
5165 if (bgp->name)
5166 vty_out (vty, " view %s", bgp->name);
5167 }
5168 vty_out (vty, "%s", VTY_NEWLINE);
5169
5170 /* No Synchronization */
5171 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5172 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5173
5174 /* BGP fast-external-failover. */
5175 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5176 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5177
5178 /* BGP router ID. */
5179 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5180 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5181 VTY_NEWLINE);
5182
paul848973c2003-08-13 00:32:49 +00005183 /* BGP log-neighbor-changes. */
5184 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5185 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5186
paul718e3742002-12-13 20:15:29 +00005187 /* BGP configuration. */
5188 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5189 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5190
5191 /* BGP default ipv4-unicast. */
5192 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5193 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5194
5195 /* BGP default local-preference. */
5196 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5197 vty_out (vty, " bgp default local-preference %d%s",
5198 bgp->default_local_pref, VTY_NEWLINE);
5199
5200 /* BGP client-to-client reflection. */
5201 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5202 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5203
5204 /* BGP cluster ID. */
5205 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5206 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5207 VTY_NEWLINE);
5208
hassoe0701b72004-05-20 09:19:34 +00005209 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005210 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005211 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5212 VTY_NEWLINE);
5213
5214 /* Confederation peer */
5215 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005216 {
hassoe0701b72004-05-20 09:19:34 +00005217 int i;
paul718e3742002-12-13 20:15:29 +00005218
hassoe0701b72004-05-20 09:19:34 +00005219 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005220
hassoe0701b72004-05-20 09:19:34 +00005221 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005222 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005223
hassoe0701b72004-05-20 09:19:34 +00005224 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005225 }
5226
5227 /* BGP enforce-first-as. */
5228 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5229 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5230
5231 /* BGP deterministic-med. */
5232 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5233 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005234
5235 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005236 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5237 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5238 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005239 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5240 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5241
paul718e3742002-12-13 20:15:29 +00005242 /* BGP bestpath method. */
5243 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5244 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005245 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5246 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005247 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5248 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5249 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5250 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5251 {
5252 vty_out (vty, " bgp bestpath med");
5253 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5254 vty_out (vty, " confed");
5255 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5256 vty_out (vty, " missing-as-worst");
5257 vty_out (vty, "%s", VTY_NEWLINE);
5258 }
5259
5260 /* BGP network import check. */
5261 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5262 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5263
5264 /* BGP scan interval. */
5265 bgp_config_write_scan_time (vty);
5266
5267 /* BGP flag dampening. */
5268 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5269 BGP_CONFIG_DAMPENING))
5270 bgp_config_write_damp (vty);
5271
5272 /* BGP static route configuration. */
5273 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5274
5275 /* BGP redistribute configuration. */
5276 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5277
5278 /* BGP timers configuration. */
5279 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5280 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5281 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5282 bgp->default_holdtime, VTY_NEWLINE);
5283
5284 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005285 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005286 {
5287 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5288 }
5289
5290 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005291 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005292 {
5293 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5294 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5295 }
5296
5297 /* Distance configuration. */
5298 bgp_config_write_distance (vty, bgp);
5299
5300 /* No auto-summary */
5301 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5302 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5303
5304 /* IPv4 multicast configuration. */
5305 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5306
5307 /* IPv4 VPN configuration. */
5308 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5309
5310 /* IPv6 unicast configuration. */
5311 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5312
Paul Jakma37a217a2007-04-10 19:20:29 +00005313 /* IPv6 multicast configuration. */
5314 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5315
paul718e3742002-12-13 20:15:29 +00005316 write++;
5317 }
5318 return write;
5319}
5320
5321void
paul94f2b392005-06-28 12:44:16 +00005322bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005323{
5324 memset (&bgp_master, 0, sizeof (struct bgp_master));
5325
5326 bm = &bgp_master;
5327 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005328 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005329 bm->port = BGP_PORT_DEFAULT;
5330 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005331 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005332}
paul200df112005-06-01 11:17:05 +00005333
paul718e3742002-12-13 20:15:29 +00005334
5335void
paul94f2b392005-06-28 12:44:16 +00005336bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005337{
paul718e3742002-12-13 20:15:29 +00005338 /* BGP VTY commands installation. */
5339 bgp_vty_init ();
5340
paul718e3742002-12-13 20:15:29 +00005341 /* Init zebra. */
5342 bgp_zebra_init ();
5343
5344 /* BGP inits. */
5345 bgp_attr_init ();
5346 bgp_debug_init ();
5347 bgp_dump_init ();
5348 bgp_route_init ();
5349 bgp_route_map_init ();
5350 bgp_scan_init ();
5351 bgp_mplsvpn_init ();
5352
5353 /* Access list initialize. */
5354 access_list_init ();
5355 access_list_add_hook (peer_distribute_update);
5356 access_list_delete_hook (peer_distribute_update);
5357
5358 /* Filter list initialize. */
5359 bgp_filter_init ();
5360 as_list_add_hook (peer_aslist_update);
5361 as_list_delete_hook (peer_aslist_update);
5362
5363 /* Prefix list initialize.*/
5364 prefix_list_init ();
5365 prefix_list_add_hook (peer_prefix_list_update);
5366 prefix_list_delete_hook (peer_prefix_list_update);
5367
5368 /* Community list initialize. */
5369 bgp_clist = community_list_init ();
5370
5371#ifdef HAVE_SNMP
5372 bgp_snmp_init ();
5373#endif /* HAVE_SNMP */
5374}
paul545acaf2004-04-20 15:13:15 +00005375
5376void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005377bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005378{
paul545acaf2004-04-20 15:13:15 +00005379 struct bgp *bgp;
5380 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005381 struct listnode *node, *nnode;
5382 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005383
paul1eb8ef22005-04-07 07:30:20 +00005384 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5385 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005386 if (peer->status == Established)
5387 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5388 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005389
paul545acaf2004-04-20 15:13:15 +00005390 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005391
paule210cf92005-06-15 19:15:35 +00005392 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005393 {
5394 work_queue_free (bm->process_main_queue);
5395 bm->process_main_queue = NULL;
5396 }
paule210cf92005-06-15 19:15:35 +00005397 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005398 {
5399 work_queue_free (bm->process_rsclient_queue);
5400 bm->process_rsclient_queue = NULL;
5401 }
paul545acaf2004-04-20 15:13:15 +00005402}