blob: bdc4e2896509d40da9b712fa7e7e2d614efc9f19 [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"
Josh Bailey165b5ff2011-07-20 20:43:22 -070060#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000061#ifdef HAVE_SNMP
62#include "bgpd/bgp_snmp.h"
63#endif /* HAVE_SNMP */
64
65/* BGP process wide configuration. */
66static struct bgp_master bgp_master;
67
hasso18a6dce2004-10-03 18:18:34 +000068extern struct in_addr router_id_zebra;
69
paul718e3742002-12-13 20:15:29 +000070/* BGP process wide configuration pointer to export. */
71struct bgp_master *bm;
72
73/* BGP community-list. */
74struct community_list_handler *bgp_clist;
75
76/* BGP global flag manipulation. */
77int
78bgp_option_set (int flag)
79{
80 switch (flag)
81 {
82 case BGP_OPT_NO_FIB:
83 case BGP_OPT_MULTIPLE_INSTANCE:
84 case BGP_OPT_CONFIG_CISCO:
85 SET_FLAG (bm->options, flag);
86 break;
87 default:
88 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000089 }
90 return 0;
91}
92
93int
94bgp_option_unset (int flag)
95{
96 switch (flag)
97 {
98 case BGP_OPT_MULTIPLE_INSTANCE:
99 if (listcount (bm->bgp) > 1)
100 return BGP_ERR_MULTIPLE_INSTANCE_USED;
101 /* Fall through. */
102 case BGP_OPT_NO_FIB:
103 case BGP_OPT_CONFIG_CISCO:
104 UNSET_FLAG (bm->options, flag);
105 break;
106 default:
107 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000108 }
109 return 0;
110}
111
112int
113bgp_option_check (int flag)
114{
115 return CHECK_FLAG (bm->options, flag);
116}
117
118/* BGP flag manipulation. */
119int
120bgp_flag_set (struct bgp *bgp, int flag)
121{
122 SET_FLAG (bgp->flags, flag);
123 return 0;
124}
125
126int
127bgp_flag_unset (struct bgp *bgp, int flag)
128{
129 UNSET_FLAG (bgp->flags, flag);
130 return 0;
131}
132
133int
134bgp_flag_check (struct bgp *bgp, int flag)
135{
136 return CHECK_FLAG (bgp->flags, flag);
137}
138
139/* Internal function to set BGP structure configureation flag. */
140static void
141bgp_config_set (struct bgp *bgp, int config)
142{
143 SET_FLAG (bgp->config, config);
144}
145
146static void
147bgp_config_unset (struct bgp *bgp, int config)
148{
149 UNSET_FLAG (bgp->config, config);
150}
151
152static int
153bgp_config_check (struct bgp *bgp, int config)
154{
155 return CHECK_FLAG (bgp->config, config);
156}
157
158/* Set BGP router identifier. */
159int
160bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
161{
162 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000163 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000164
165 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
166 && IPV4_ADDR_SAME (&bgp->router_id, id))
167 return 0;
168
169 IPV4_ADDR_COPY (&bgp->router_id, id);
170 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
171
172 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000174 {
175 IPV4_ADDR_COPY (&peer->local_id, id);
176
177 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000178 {
179 peer->last_reset = PEER_DOWN_RID_CHANGE;
180 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
181 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
182 }
paul718e3742002-12-13 20:15:29 +0000183 }
184 return 0;
185}
186
paul718e3742002-12-13 20:15:29 +0000187/* BGP's cluster-id control. */
188int
189bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
190{
191 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000192 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000193
194 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
195 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
196 return 0;
197
198 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
199 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
200
201 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000202 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000203 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000204 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000205 continue;
206
207 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000208 {
209 peer->last_reset = PEER_DOWN_CLID_CHANGE;
210 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
211 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
212 }
paul718e3742002-12-13 20:15:29 +0000213 }
214 return 0;
215}
216
217int
218bgp_cluster_id_unset (struct bgp *bgp)
219{
220 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000221 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000222
223 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
224 return 0;
225
226 bgp->cluster_id.s_addr = 0;
227 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
228
229 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000230 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000231 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000232 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000233 continue;
234
235 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000236 {
237 peer->last_reset = PEER_DOWN_CLID_CHANGE;
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
239 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
240 }
paul718e3742002-12-13 20:15:29 +0000241 }
242 return 0;
243}
244
Stephen Hemminger65957882010-01-15 16:22:10 +0300245/* time_t value that is monotonicly increasing
246 * and uneffected by adjustments to system clock
247 */
248time_t bgp_clock (void)
249{
250 struct timeval tv;
251
252 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
253 return tv.tv_sec;
254}
255
paul718e3742002-12-13 20:15:29 +0000256/* BGP timer configuration. */
257int
258bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
259{
260 bgp->default_keepalive = (keepalive < holdtime / 3
261 ? keepalive : holdtime / 3);
262 bgp->default_holdtime = holdtime;
263
264 return 0;
265}
266
267int
268bgp_timers_unset (struct bgp *bgp)
269{
270 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
271 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
272
273 return 0;
274}
275
276/* BGP confederation configuration. */
277int
278bgp_confederation_id_set (struct bgp *bgp, as_t as)
279{
280 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000281 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000282 int already_confed;
283
284 if (as == 0)
285 return BGP_ERR_INVALID_AS;
286
287 /* Remember - were we doing confederation before? */
288 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
289 bgp->confed_id = as;
290 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
291
292 /* If we were doing confederation already, this is just an external
293 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
294 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000295 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000296 {
297 /* We're looking for peers who's AS is not local or part of our
298 confederation. */
299 if (already_confed)
300 {
301 if (peer_sort (peer) == BGP_PEER_EBGP)
302 {
303 peer->local_as = as;
304 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000305 {
306 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
307 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
308 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
309 }
310
paul718e3742002-12-13 20:15:29 +0000311 else
312 BGP_EVENT_ADD (peer, BGP_Stop);
313 }
314 }
315 else
316 {
317 /* Not doign confederation before, so reset every non-local
318 session */
319 if (peer_sort (peer) != BGP_PEER_IBGP)
320 {
321 /* Reset the local_as to be our EBGP one */
322 if (peer_sort (peer) == BGP_PEER_EBGP)
323 peer->local_as = as;
324 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000325 {
326 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
327 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
328 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
329 }
paul718e3742002-12-13 20:15:29 +0000330 else
331 BGP_EVENT_ADD (peer, BGP_Stop);
332 }
333 }
334 }
335 return 0;
336}
337
338int
339bgp_confederation_id_unset (struct bgp *bgp)
340{
341 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000342 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000343
344 bgp->confed_id = 0;
345 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
346
paul1eb8ef22005-04-07 07:30:20 +0000347 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000348 {
349 /* We're looking for peers who's AS is not local */
350 if (peer_sort (peer) != BGP_PEER_IBGP)
351 {
352 peer->local_as = bgp->as;
353 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000354 {
355 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
356 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
357 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
358 }
359
paul718e3742002-12-13 20:15:29 +0000360 else
361 BGP_EVENT_ADD (peer, BGP_Stop);
362 }
363 }
364 return 0;
365}
366
367/* Is an AS part of the confed or not? */
368int
369bgp_confederation_peers_check (struct bgp *bgp, as_t as)
370{
371 int i;
372
373 if (! bgp)
374 return 0;
375
376 for (i = 0; i < bgp->confed_peers_cnt; i++)
377 if (bgp->confed_peers[i] == as)
378 return 1;
379
380 return 0;
381}
382
383/* Add an AS to the confederation set. */
384int
385bgp_confederation_peers_add (struct bgp *bgp, as_t as)
386{
387 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000389
390 if (! bgp)
391 return BGP_ERR_INVALID_BGP;
392
393 if (bgp->as == as)
394 return BGP_ERR_INVALID_AS;
395
396 if (bgp_confederation_peers_check (bgp, as))
397 return -1;
398
399 if (bgp->confed_peers)
400 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
401 bgp->confed_peers,
402 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
403 else
404 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
405 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
406
407 bgp->confed_peers[bgp->confed_peers_cnt] = as;
408 bgp->confed_peers_cnt++;
409
410 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
411 {
paul1eb8ef22005-04-07 07:30:20 +0000412 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000413 {
414 if (peer->as == as)
415 {
416 peer->local_as = bgp->as;
417 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000418 {
419 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
420 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
421 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
422 }
paul718e3742002-12-13 20:15:29 +0000423 else
424 BGP_EVENT_ADD (peer, BGP_Stop);
425 }
426 }
427 }
428 return 0;
429}
430
431/* Delete an AS from the confederation set. */
432int
433bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
434{
435 int i;
436 int j;
437 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000438 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000439
440 if (! bgp)
441 return -1;
442
443 if (! bgp_confederation_peers_check (bgp, as))
444 return -1;
445
446 for (i = 0; i < bgp->confed_peers_cnt; i++)
447 if (bgp->confed_peers[i] == as)
448 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
449 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
450
451 bgp->confed_peers_cnt--;
452
453 if (bgp->confed_peers_cnt == 0)
454 {
455 if (bgp->confed_peers)
456 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
457 bgp->confed_peers = NULL;
458 }
459 else
460 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
461 bgp->confed_peers,
462 bgp->confed_peers_cnt * sizeof (as_t));
463
464 /* Now reset any peer who's remote AS has just been removed from the
465 CONFED */
466 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
467 {
paul1eb8ef22005-04-07 07:30:20 +0000468 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000469 {
470 if (peer->as == as)
471 {
472 peer->local_as = bgp->confed_id;
473 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000474 {
475 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
476 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
477 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
478 }
paul718e3742002-12-13 20:15:29 +0000479 else
480 BGP_EVENT_ADD (peer, BGP_Stop);
481 }
482 }
483 }
484
485 return 0;
486}
487
488/* Local preference configuration. */
489int
490bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
491{
492 if (! bgp)
493 return -1;
494
paul718e3742002-12-13 20:15:29 +0000495 bgp->default_local_pref = local_pref;
496
497 return 0;
498}
499
500int
501bgp_default_local_preference_unset (struct bgp *bgp)
502{
503 if (! bgp)
504 return -1;
505
paul718e3742002-12-13 20:15:29 +0000506 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
507
508 return 0;
509}
510
paulfee0f4c2004-09-13 05:12:46 +0000511/* If peer is RSERVER_CLIENT in at least one address family and is not member
512 of a peer_group for that family, return 1.
513 Used to check wether the peer is included in list bgp->rsclient. */
514int
515peer_rsclient_active (struct peer *peer)
516{
517 int i;
518 int j;
519
520 for (i=AFI_IP; i < AFI_MAX; i++)
521 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
522 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
523 && ! peer->af_group[i][j])
524 return 1;
525 return 0;
526}
527
pauleb821182004-05-01 08:44:08 +0000528/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000529static int
530peer_cmp (struct peer *p1, struct peer *p2)
531{
pauleb821182004-05-01 08:44:08 +0000532 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000533}
534
535int
536peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
537{
538 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
539}
540
541/* Reset all address family specific configuration. */
542static void
543peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
544{
545 int i;
546 struct bgp_filter *filter;
547 char orf_name[BUFSIZ];
548
549 filter = &peer->filter[afi][safi];
550
551 /* Clear neighbor filter and route-map */
552 for (i = FILTER_IN; i < FILTER_MAX; i++)
553 {
554 if (filter->dlist[i].name)
555 {
556 free (filter->dlist[i].name);
557 filter->dlist[i].name = NULL;
558 }
559 if (filter->plist[i].name)
560 {
561 free (filter->plist[i].name);
562 filter->plist[i].name = NULL;
563 }
564 if (filter->aslist[i].name)
565 {
566 free (filter->aslist[i].name);
567 filter->aslist[i].name = NULL;
568 }
paulfee0f4c2004-09-13 05:12:46 +0000569 }
570 for (i = RMAP_IN; i < RMAP_MAX; i++)
571 {
paul718e3742002-12-13 20:15:29 +0000572 if (filter->map[i].name)
573 {
574 free (filter->map[i].name);
575 filter->map[i].name = NULL;
576 }
577 }
578
579 /* Clear unsuppress map. */
580 if (filter->usmap.name)
581 free (filter->usmap.name);
582 filter->usmap.name = NULL;
583 filter->usmap.map = NULL;
584
585 /* Clear neighbor's all address family flags. */
586 peer->af_flags[afi][safi] = 0;
587
588 /* Clear neighbor's all address family sflags. */
589 peer->af_sflags[afi][safi] = 0;
590
591 /* Clear neighbor's all address family capabilities. */
592 peer->af_cap[afi][safi] = 0;
593
594 /* Clear ORF info */
595 peer->orf_plist[afi][safi] = NULL;
596 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
597 prefix_bgp_orf_remove_all (orf_name);
598
599 /* Set default neighbor send-community. */
600 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
601 {
602 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
604 }
605
606 /* Clear neighbor default_originate_rmap */
607 if (peer->default_rmap[afi][safi].name)
608 free (peer->default_rmap[afi][safi].name);
609 peer->default_rmap[afi][safi].name = NULL;
610 peer->default_rmap[afi][safi].map = NULL;
611
612 /* Clear neighbor maximum-prefix */
613 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000614 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000615}
616
617/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000618static void
paul718e3742002-12-13 20:15:29 +0000619peer_global_config_reset (struct peer *peer)
620{
621 peer->weight = 0;
622 peer->change_local_as = 0;
623 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
624 if (peer->update_source)
625 {
626 sockunion_free (peer->update_source);
627 peer->update_source = NULL;
628 }
629 if (peer->update_if)
630 {
631 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
632 peer->update_if = NULL;
633 }
634
635 if (peer_sort (peer) == BGP_PEER_IBGP)
636 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
637 else
638 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
639
640 peer->flags = 0;
641 peer->config = 0;
642 peer->holdtime = 0;
643 peer->keepalive = 0;
644 peer->connect = 0;
645 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
646}
647
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000648/* Check peer's AS number and determines if this peer is IBGP or EBGP */
649static bgp_peer_sort_t
650peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000651{
652 struct bgp *bgp;
653
654 bgp = peer->bgp;
655
656 /* Peer-group */
657 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
658 {
659 if (peer->as)
660 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
661 else
662 {
663 struct peer *peer1;
664 peer1 = listnode_head (peer->group->peer);
665 if (peer1)
666 return (peer1->local_as == peer1->as
667 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
668 }
669 return BGP_PEER_INTERNAL;
670 }
671
672 /* Normal peer */
673 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
674 {
675 if (peer->local_as == 0)
676 return BGP_PEER_INTERNAL;
677
678 if (peer->local_as == peer->as)
679 {
680 if (peer->local_as == bgp->confed_id)
681 return BGP_PEER_EBGP;
682 else
683 return BGP_PEER_IBGP;
684 }
685
686 if (bgp_confederation_peers_check (bgp, peer->as))
687 return BGP_PEER_CONFED;
688
689 return BGP_PEER_EBGP;
690 }
691 else
692 {
693 return (peer->local_as == 0
694 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
695 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
696 }
697}
698
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000699/* Calculate and cache the peer "sort" */
700bgp_peer_sort_t
701peer_sort (struct peer *peer)
702{
703 peer->sort = peer_calc_sort (peer);
704 return peer->sort;
705}
706
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100707static void
paul200df112005-06-01 11:17:05 +0000708peer_free (struct peer *peer)
709{
Paul Jakmaca058a32006-09-14 02:58:49 +0000710 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700711
712 bgp_unlock(peer->bgp);
713
Paul Jakmaca058a32006-09-14 02:58:49 +0000714 /* this /ought/ to have been done already through bgp_stop earlier,
715 * but just to be sure..
716 */
717 bgp_timer_set (peer);
718 BGP_READ_OFF (peer->t_read);
719 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000720 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000721
paul200df112005-06-01 11:17:05 +0000722 if (peer->desc)
723 XFREE (MTYPE_PEER_DESC, peer->desc);
724
725 /* Free allocated host character. */
726 if (peer->host)
727 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
728
729 /* Update source configuration. */
730 if (peer->update_source)
731 sockunion_free (peer->update_source);
732
733 if (peer->update_if)
734 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000735
736 if (peer->clear_node_queue)
737 work_queue_free (peer->clear_node_queue);
738
Paul Jakmaca058a32006-09-14 02:58:49 +0000739 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000740 memset (peer, 0, sizeof (struct peer));
741
742 XFREE (MTYPE_BGP_PEER, peer);
743}
744
745/* increase reference count on a struct peer */
746struct peer *
747peer_lock (struct peer *peer)
748{
749 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000750
paul200df112005-06-01 11:17:05 +0000751 peer->lock++;
752
753 return peer;
754}
755
756/* decrease reference count on a struct peer
757 * struct peer is freed and NULL returned if last reference
758 */
759struct peer *
760peer_unlock (struct peer *peer)
761{
762 assert (peer && (peer->lock > 0));
763
764 peer->lock--;
765
766 if (peer->lock == 0)
767 {
768#if 0
769 zlog_debug ("unlocked and freeing");
770 zlog_backtrace (LOG_DEBUG);
771#endif
772 peer_free (peer);
773 return NULL;
774 }
775
776#if 0
777 if (peer->lock == 1)
778 {
779 zlog_debug ("unlocked to 1");
780 zlog_backtrace (LOG_DEBUG);
781 }
782#endif
783
784 return peer;
785}
786
787/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000788static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000789peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000790{
791 afi_t afi;
792 safi_t safi;
793 struct peer *peer;
794 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000795
796 /* bgp argument is absolutely required */
797 assert (bgp);
798 if (!bgp)
799 return NULL;
800
paul718e3742002-12-13 20:15:29 +0000801 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000802 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000803
804 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000805 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000806 peer->v_start = BGP_INIT_START_TIMER;
807 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
808 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
809 peer->status = Idle;
810 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000811 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000812 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000813 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000814 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700815 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000816
817 /* Set default flags. */
818 for (afi = AFI_IP; afi < AFI_MAX; afi++)
819 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
820 {
821 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
822 {
823 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
824 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
825 }
826 peer->orf_plist[afi][safi] = NULL;
827 }
828 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
829
830 /* Create buffers. */
831 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
832 peer->obuf = stream_fifo_new ();
833 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
834
835 bgp_sync_init (peer);
836
837 /* Get service port number. */
838 sp = getservbyname ("bgp", "tcp");
839 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
840
841 return peer;
842}
843
844/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000845static struct peer *
paul718e3742002-12-13 20:15:29 +0000846peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
847 as_t remote_as, afi_t afi, safi_t safi)
848{
849 int active;
850 struct peer *peer;
851 char buf[SU_ADDRSTRLEN];
852
Paul Jakma6f585442006-10-22 19:13:07 +0000853 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000854 peer->su = *su;
855 peer->local_as = local_as;
856 peer->as = remote_as;
857 peer->local_id = bgp->router_id;
858 peer->v_holdtime = bgp->default_holdtime;
859 peer->v_keepalive = bgp->default_keepalive;
860 if (peer_sort (peer) == BGP_PEER_IBGP)
861 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
862 else
863 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000864
865 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000866 listnode_add_sort (bgp->peer, peer);
867
868 active = peer_active (peer);
869
870 if (afi && safi)
871 peer->afc[afi][safi] = 1;
872
Stephen Hemminger65957882010-01-15 16:22:10 +0300873 /* Last read and reset time set */
874 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000875
paul718e3742002-12-13 20:15:29 +0000876 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000877 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000878
879 /* Make peer's address string. */
880 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000881 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000882
883 /* Set up peer's events and timers. */
884 if (! active && peer_active (peer))
885 bgp_timer_set (peer);
886
887 return peer;
888}
889
pauleb821182004-05-01 08:44:08 +0000890/* Make accept BGP peer. Called from bgp_accept (). */
891struct peer *
892peer_create_accept (struct bgp *bgp)
893{
894 struct peer *peer;
895
Paul Jakma6f585442006-10-22 19:13:07 +0000896 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000897
898 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000899 listnode_add_sort (bgp->peer, peer);
900
901 return peer;
902}
903
paul718e3742002-12-13 20:15:29 +0000904/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000905static void
paul718e3742002-12-13 20:15:29 +0000906peer_as_change (struct peer *peer, as_t as)
907{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000908 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000909
910 /* Stop peer. */
911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
912 {
913 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000914 {
915 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
916 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
917 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
918 }
paul718e3742002-12-13 20:15:29 +0000919 else
920 BGP_EVENT_ADD (peer, BGP_Stop);
921 }
922 type = peer_sort (peer);
923 peer->as = as;
924
paul848973c2003-08-13 00:32:49 +0000925 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
926 && ! bgp_confederation_peers_check (peer->bgp, as)
927 && peer->bgp->as != as)
928 peer->local_as = peer->bgp->confed_id;
929 else
930 peer->local_as = peer->bgp->as;
931
paul718e3742002-12-13 20:15:29 +0000932 /* Advertisement-interval reset */
933 if (peer_sort (peer) == BGP_PEER_IBGP)
934 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
935 else
936 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
937
938 /* TTL reset */
939 if (peer_sort (peer) == BGP_PEER_IBGP)
940 peer->ttl = 255;
941 else if (type == BGP_PEER_IBGP)
942 peer->ttl = 1;
943
944 /* reflector-client reset */
945 if (peer_sort (peer) != BGP_PEER_IBGP)
946 {
947 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
948 PEER_FLAG_REFLECTOR_CLIENT);
949 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
950 PEER_FLAG_REFLECTOR_CLIENT);
951 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
952 PEER_FLAG_REFLECTOR_CLIENT);
953 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
954 PEER_FLAG_REFLECTOR_CLIENT);
955 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
956 PEER_FLAG_REFLECTOR_CLIENT);
957 }
958
959 /* local-as reset */
960 if (peer_sort (peer) != BGP_PEER_EBGP)
961 {
962 peer->change_local_as = 0;
963 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
964 }
965}
966
967/* If peer does not exist, create new one. If peer already exists,
968 set AS number to the peer. */
969int
970peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
971 afi_t afi, safi_t safi)
972{
973 struct peer *peer;
974 as_t local_as;
975
976 peer = peer_lookup (bgp, su);
977
978 if (peer)
979 {
980 /* When this peer is a member of peer-group. */
981 if (peer->group)
982 {
983 if (peer->group->conf->as)
984 {
985 /* Return peer group's AS number. */
986 *as = peer->group->conf->as;
987 return BGP_ERR_PEER_GROUP_MEMBER;
988 }
989 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
990 {
991 if (bgp->as != *as)
992 {
993 *as = peer->as;
994 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
995 }
996 }
997 else
998 {
999 if (bgp->as == *as)
1000 {
1001 *as = peer->as;
1002 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1003 }
1004 }
1005 }
1006
1007 /* Existing peer's AS number change. */
1008 if (peer->as != *as)
1009 peer_as_change (peer, *as);
1010 }
1011 else
1012 {
1013
1014 /* If the peer is not part of our confederation, and its not an
1015 iBGP peer then spoof the source AS */
1016 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1017 && ! bgp_confederation_peers_check (bgp, *as)
1018 && bgp->as != *as)
1019 local_as = bgp->confed_id;
1020 else
1021 local_as = bgp->as;
1022
1023 /* If this is IPv4 unicast configuration and "no bgp default
1024 ipv4-unicast" is specified. */
1025
1026 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1027 && afi == AFI_IP && safi == SAFI_UNICAST)
1028 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1029 else
1030 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1031 }
1032
1033 return 0;
1034}
1035
1036/* Activate the peer or peer group for specified AFI and SAFI. */
1037int
1038peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1039{
1040 int active;
1041
1042 if (peer->afc[afi][safi])
1043 return 0;
1044
1045 /* Activate the address family configuration. */
1046 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1047 peer->afc[afi][safi] = 1;
1048 else
1049 {
1050 active = peer_active (peer);
1051
1052 peer->afc[afi][safi] = 1;
1053
1054 if (! active && peer_active (peer))
1055 bgp_timer_set (peer);
1056 else
1057 {
1058 if (peer->status == Established)
1059 {
1060 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1061 {
1062 peer->afc_adv[afi][safi] = 1;
1063 bgp_capability_send (peer, afi, safi,
1064 CAPABILITY_CODE_MP,
1065 CAPABILITY_ACTION_SET);
1066 if (peer->afc_recv[afi][safi])
1067 {
1068 peer->afc_nego[afi][safi] = 1;
1069 bgp_announce_route (peer, afi, safi);
1070 }
1071 }
1072 else
hassoe0701b72004-05-20 09:19:34 +00001073 {
1074 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1075 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1076 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1077 }
paul718e3742002-12-13 20:15:29 +00001078 }
1079 }
1080 }
1081 return 0;
1082}
1083
1084int
1085peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1086{
1087 struct peer_group *group;
1088 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001089 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001090
1091 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1092 {
1093 group = peer->group;
1094
paul1eb8ef22005-04-07 07:30:20 +00001095 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001096 {
1097 if (peer1->af_group[afi][safi])
1098 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1099 }
1100 }
1101 else
1102 {
1103 if (peer->af_group[afi][safi])
1104 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1105 }
1106
1107 if (! peer->afc[afi][safi])
1108 return 0;
1109
1110 /* De-activate the address family configuration. */
1111 peer->afc[afi][safi] = 0;
1112 peer_af_flag_reset (peer, afi, safi);
1113
1114 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1115 {
1116 if (peer->status == Established)
1117 {
1118 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1119 {
1120 peer->afc_adv[afi][safi] = 0;
1121 peer->afc_nego[afi][safi] = 0;
1122
1123 if (peer_active_nego (peer))
1124 {
1125 bgp_capability_send (peer, afi, safi,
1126 CAPABILITY_CODE_MP,
1127 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001128 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001129 peer->pcount[afi][safi] = 0;
1130 }
1131 else
hassoe0701b72004-05-20 09:19:34 +00001132 {
1133 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1134 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1135 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1136 }
paul718e3742002-12-13 20:15:29 +00001137 }
1138 else
hassoe0701b72004-05-20 09:19:34 +00001139 {
1140 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1141 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1142 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1143 }
paul718e3742002-12-13 20:15:29 +00001144 }
1145 }
1146 return 0;
1147}
1148
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001149static void
hasso93406d82005-02-02 14:40:33 +00001150peer_nsf_stop (struct peer *peer)
1151{
1152 afi_t afi;
1153 safi_t safi;
1154
1155 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1156 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1157
1158 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001159 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001160 peer->nsf[afi][safi] = 0;
1161
1162 if (peer->t_gr_restart)
1163 {
1164 BGP_TIMER_OFF (peer->t_gr_restart);
1165 if (BGP_DEBUG (events, EVENTS))
1166 zlog_debug ("%s graceful restart timer stopped", peer->host);
1167 }
1168 if (peer->t_gr_stale)
1169 {
1170 BGP_TIMER_OFF (peer->t_gr_stale);
1171 if (BGP_DEBUG (events, EVENTS))
1172 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1173 }
1174 bgp_clear_route_all (peer);
1175}
1176
Paul Jakmaca058a32006-09-14 02:58:49 +00001177/* Delete peer from confguration.
1178 *
1179 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1180 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1181 *
1182 * This function /should/ take care to be idempotent, to guard against
1183 * it being called multiple times through stray events that come in
1184 * that happen to result in this function being called again. That
1185 * said, getting here for a "Deleted" peer is a bug in the neighbour
1186 * FSM.
1187 */
paul718e3742002-12-13 20:15:29 +00001188int
1189peer_delete (struct peer *peer)
1190{
1191 int i;
1192 afi_t afi;
1193 safi_t safi;
1194 struct bgp *bgp;
1195 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001196 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001197
Paul Jakmaca058a32006-09-14 02:58:49 +00001198 assert (peer->status != Deleted);
1199
paul718e3742002-12-13 20:15:29 +00001200 bgp = peer->bgp;
1201
hasso93406d82005-02-02 14:40:33 +00001202 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1203 peer_nsf_stop (peer);
1204
Chris Caputo228da422009-07-18 05:44:03 +00001205 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001206 relationship. */
1207 if (peer->group)
1208 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001209 if ((pn = listnode_lookup (peer->group->peer, peer)))
1210 {
1211 peer = peer_unlock (peer); /* group->peer list reference */
1212 list_delete_node (peer->group->peer, pn);
1213 }
paul718e3742002-12-13 20:15:29 +00001214 peer->group = NULL;
1215 }
paul200df112005-06-01 11:17:05 +00001216
paul718e3742002-12-13 20:15:29 +00001217 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001218 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1219 * executed after peer structure is deleted.
1220 */
hassoe0701b72004-05-20 09:19:34 +00001221 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001222 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001223 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001224
1225 /* Password configuration */
1226 if (peer->password)
1227 {
1228 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1229 peer->password = NULL;
1230
1231 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1232 bgp_md5_set (peer);
1233 }
1234
Paul Jakmaca058a32006-09-14 02:58:49 +00001235 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001236
paul718e3742002-12-13 20:15:29 +00001237 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001238 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1239 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001240 {
Chris Caputo228da422009-07-18 05:44:03 +00001241 peer_unlock (peer); /* bgp peer list reference */
1242 list_delete_node (bgp->peer, pn);
1243 }
paul200df112005-06-01 11:17:05 +00001244
Chris Caputo228da422009-07-18 05:44:03 +00001245 if (peer_rsclient_active (peer)
1246 && (pn = listnode_lookup (bgp->rsclient, peer)))
1247 {
1248 peer_unlock (peer); /* rsclient list reference */
1249 list_delete_node (bgp->rsclient, pn);
1250
1251 /* Clear our own rsclient ribs. */
1252 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1253 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1254 if (CHECK_FLAG(peer->af_flags[afi][safi],
1255 PEER_FLAG_RSERVER_CLIENT))
1256 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001257 }
1258
1259 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1260 member of a peer_group. */
1261 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1262 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1263 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001264 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001265
paul200df112005-06-01 11:17:05 +00001266 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001267 if (peer->ibuf)
1268 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001269 if (peer->obuf)
1270 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001271 if (peer->work)
1272 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001273 peer->obuf = NULL;
1274 peer->work = peer->ibuf = NULL;
1275
paul718e3742002-12-13 20:15:29 +00001276 /* Local and remote addresses. */
1277 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001278 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001279 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001280 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001281 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001282
paul718e3742002-12-13 20:15:29 +00001283 /* Free filter related memory. */
1284 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1285 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1286 {
1287 filter = &peer->filter[afi][safi];
1288
1289 for (i = FILTER_IN; i < FILTER_MAX; i++)
1290 {
1291 if (filter->dlist[i].name)
1292 free (filter->dlist[i].name);
1293 if (filter->plist[i].name)
1294 free (filter->plist[i].name);
1295 if (filter->aslist[i].name)
1296 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001297
1298 filter->dlist[i].name = NULL;
1299 filter->plist[i].name = NULL;
1300 filter->aslist[i].name = NULL;
1301 }
1302 for (i = RMAP_IN; i < RMAP_MAX; i++)
1303 {
paul718e3742002-12-13 20:15:29 +00001304 if (filter->map[i].name)
1305 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001306 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001307 }
1308
1309 if (filter->usmap.name)
1310 free (filter->usmap.name);
1311
1312 if (peer->default_rmap[afi][safi].name)
1313 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001314
1315 filter->usmap.name = NULL;
1316 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001317 }
paul200df112005-06-01 11:17:05 +00001318
1319 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001320
1321 return 0;
1322}
1323
paul94f2b392005-06-28 12:44:16 +00001324static int
paul718e3742002-12-13 20:15:29 +00001325peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1326{
1327 return strcmp (g1->name, g2->name);
1328}
1329
1330/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001331static int
paul718e3742002-12-13 20:15:29 +00001332peer_group_active (struct peer *peer)
1333{
1334 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1335 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1336 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1337 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1338 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1339 return 1;
1340 return 0;
1341}
1342
1343/* Peer group cofiguration. */
1344static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001345peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001346{
1347 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1348 sizeof (struct peer_group));
1349}
1350
paul94f2b392005-06-28 12:44:16 +00001351static void
paul718e3742002-12-13 20:15:29 +00001352peer_group_free (struct peer_group *group)
1353{
1354 XFREE (MTYPE_PEER_GROUP, group);
1355}
1356
1357struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001358peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001359{
1360 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001361 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001362
paul1eb8ef22005-04-07 07:30:20 +00001363 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001364 {
1365 if (strcmp (group->name, name) == 0)
1366 return group;
1367 }
1368 return NULL;
1369}
1370
1371struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001372peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001373{
1374 struct peer_group *group;
1375
1376 group = peer_group_lookup (bgp, name);
1377 if (group)
1378 return group;
1379
1380 group = peer_group_new ();
1381 group->bgp = bgp;
1382 group->name = strdup (name);
1383 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001384 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001385 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1386 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001387 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001388 group->conf->group = group;
1389 group->conf->as = 0;
1390 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001391 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001392 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1393 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1394 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1395 group->conf->keepalive = 0;
1396 group->conf->holdtime = 0;
1397 group->conf->connect = 0;
1398 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1399 listnode_add_sort (bgp->group, group);
1400
1401 return 0;
1402}
1403
paul94f2b392005-06-28 12:44:16 +00001404static void
paul718e3742002-12-13 20:15:29 +00001405peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1406 afi_t afi, safi_t safi)
1407{
1408 int in = FILTER_IN;
1409 int out = FILTER_OUT;
1410 struct peer *conf;
1411 struct bgp_filter *pfilter;
1412 struct bgp_filter *gfilter;
1413
1414 conf = group->conf;
1415 pfilter = &peer->filter[afi][safi];
1416 gfilter = &conf->filter[afi][safi];
1417
1418 /* remote-as */
1419 if (conf->as)
1420 peer->as = conf->as;
1421
1422 /* remote-as */
1423 if (conf->change_local_as)
1424 peer->change_local_as = conf->change_local_as;
1425
1426 /* TTL */
1427 peer->ttl = conf->ttl;
1428
Nick Hilliardfa411a22011-03-23 15:33:17 +00001429 /* GTSM hops */
1430 peer->gtsm_hops = conf->gtsm_hops;
1431
paul718e3742002-12-13 20:15:29 +00001432 /* Weight */
1433 peer->weight = conf->weight;
1434
1435 /* peer flags apply */
1436 peer->flags = conf->flags;
1437 /* peer af_flags apply */
1438 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1439 /* peer config apply */
1440 peer->config = conf->config;
1441
1442 /* peer timers apply */
1443 peer->holdtime = conf->holdtime;
1444 peer->keepalive = conf->keepalive;
1445 peer->connect = conf->connect;
1446 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1447 peer->v_connect = conf->connect;
1448 else
1449 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1450
1451 /* advertisement-interval reset */
1452 if (peer_sort (peer) == BGP_PEER_IBGP)
1453 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1454 else
1455 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1456
Paul Jakma0df7c912008-07-21 21:02:49 +00001457 /* password apply */
1458 if (peer->password)
1459 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1460
1461 if (conf->password)
1462 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1463 else
1464 peer->password = NULL;
1465
1466 bgp_md5_set (peer);
1467
paul718e3742002-12-13 20:15:29 +00001468 /* maximum-prefix */
1469 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001470 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001471 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001472
1473 /* allowas-in */
1474 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1475
paulfee0f4c2004-09-13 05:12:46 +00001476 /* route-server-client */
1477 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1478 {
1479 /* Make peer's RIB point to group's RIB. */
1480 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1481
1482 /* Import policy. */
1483 if (pfilter->map[RMAP_IMPORT].name)
1484 free (pfilter->map[RMAP_IMPORT].name);
1485 if (gfilter->map[RMAP_IMPORT].name)
1486 {
1487 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1488 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1489 }
1490 else
1491 {
1492 pfilter->map[RMAP_IMPORT].name = NULL;
1493 pfilter->map[RMAP_IMPORT].map = NULL;
1494 }
1495
1496 /* Export policy. */
1497 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1498 {
1499 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1500 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1501 }
1502 }
1503
paul718e3742002-12-13 20:15:29 +00001504 /* default-originate route-map */
1505 if (conf->default_rmap[afi][safi].name)
1506 {
1507 if (peer->default_rmap[afi][safi].name)
1508 free (peer->default_rmap[afi][safi].name);
1509 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1510 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1511 }
1512
1513 /* update-source apply */
1514 if (conf->update_source)
1515 {
1516 if (peer->update_source)
1517 sockunion_free (peer->update_source);
1518 if (peer->update_if)
1519 {
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 peer->update_if = NULL;
1522 }
1523 peer->update_source = sockunion_dup (conf->update_source);
1524 }
1525 else if (conf->update_if)
1526 {
1527 if (peer->update_if)
1528 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1529 if (peer->update_source)
1530 {
1531 sockunion_free (peer->update_source);
1532 peer->update_source = NULL;
1533 }
1534 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1535 }
1536
1537 /* inbound filter apply */
1538 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1539 {
1540 if (pfilter->dlist[in].name)
1541 free (pfilter->dlist[in].name);
1542 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1543 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1544 }
1545 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1546 {
1547 if (pfilter->plist[in].name)
1548 free (pfilter->plist[in].name);
1549 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1550 pfilter->plist[in].plist = gfilter->plist[in].plist;
1551 }
1552 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1553 {
1554 if (pfilter->aslist[in].name)
1555 free (pfilter->aslist[in].name);
1556 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1557 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1558 }
paulfee0f4c2004-09-13 05:12:46 +00001559 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001560 {
paulfee0f4c2004-09-13 05:12:46 +00001561 if (pfilter->map[RMAP_IN].name)
1562 free (pfilter->map[RMAP_IN].name);
1563 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1564 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001565 }
1566
1567 /* outbound filter apply */
1568 if (gfilter->dlist[out].name)
1569 {
1570 if (pfilter->dlist[out].name)
1571 free (pfilter->dlist[out].name);
1572 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1573 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1574 }
1575 else
1576 {
1577 if (pfilter->dlist[out].name)
1578 free (pfilter->dlist[out].name);
1579 pfilter->dlist[out].name = NULL;
1580 pfilter->dlist[out].alist = NULL;
1581 }
1582 if (gfilter->plist[out].name)
1583 {
1584 if (pfilter->plist[out].name)
1585 free (pfilter->plist[out].name);
1586 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1587 pfilter->plist[out].plist = gfilter->plist[out].plist;
1588 }
1589 else
1590 {
1591 if (pfilter->plist[out].name)
1592 free (pfilter->plist[out].name);
1593 pfilter->plist[out].name = NULL;
1594 pfilter->plist[out].plist = NULL;
1595 }
1596 if (gfilter->aslist[out].name)
1597 {
1598 if (pfilter->aslist[out].name)
1599 free (pfilter->aslist[out].name);
1600 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1601 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1602 }
1603 else
1604 {
1605 if (pfilter->aslist[out].name)
1606 free (pfilter->aslist[out].name);
1607 pfilter->aslist[out].name = NULL;
1608 pfilter->aslist[out].aslist = NULL;
1609 }
paulfee0f4c2004-09-13 05:12:46 +00001610 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001611 {
paulfee0f4c2004-09-13 05:12:46 +00001612 if (pfilter->map[RMAP_OUT].name)
1613 free (pfilter->map[RMAP_OUT].name);
1614 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1615 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001616 }
1617 else
1618 {
paulfee0f4c2004-09-13 05:12:46 +00001619 if (pfilter->map[RMAP_OUT].name)
1620 free (pfilter->map[RMAP_OUT].name);
1621 pfilter->map[RMAP_OUT].name = NULL;
1622 pfilter->map[RMAP_OUT].map = NULL;
1623 }
1624
1625 /* RS-client's import/export route-maps. */
1626 if (gfilter->map[RMAP_IMPORT].name)
1627 {
1628 if (pfilter->map[RMAP_IMPORT].name)
1629 free (pfilter->map[RMAP_IMPORT].name);
1630 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1631 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1632 }
1633 else
1634 {
1635 if (pfilter->map[RMAP_IMPORT].name)
1636 free (pfilter->map[RMAP_IMPORT].name);
1637 pfilter->map[RMAP_IMPORT].name = NULL;
1638 pfilter->map[RMAP_IMPORT].map = NULL;
1639 }
1640 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1641 {
1642 if (pfilter->map[RMAP_EXPORT].name)
1643 free (pfilter->map[RMAP_EXPORT].name);
1644 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1645 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001646 }
1647
1648 if (gfilter->usmap.name)
1649 {
1650 if (pfilter->usmap.name)
1651 free (pfilter->usmap.name);
1652 pfilter->usmap.name = strdup (gfilter->usmap.name);
1653 pfilter->usmap.map = gfilter->usmap.map;
1654 }
1655 else
1656 {
1657 if (pfilter->usmap.name)
1658 free (pfilter->usmap.name);
1659 pfilter->usmap.name = NULL;
1660 pfilter->usmap.map = NULL;
1661 }
1662}
1663
1664/* Peer group's remote AS configuration. */
1665int
paulfd79ac92004-10-13 05:06:08 +00001666peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001667{
1668 struct peer_group *group;
1669 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001670 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001671
1672 group = peer_group_lookup (bgp, group_name);
1673 if (! group)
1674 return -1;
1675
1676 if (group->conf->as == *as)
1677 return 0;
1678
1679 /* When we setup peer-group AS number all peer group member's AS
1680 number must be updated to same number. */
1681 peer_as_change (group->conf, *as);
1682
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001684 {
1685 if (peer->as != *as)
1686 peer_as_change (peer, *as);
1687 }
1688
1689 return 0;
1690}
1691
1692int
1693peer_group_delete (struct peer_group *group)
1694{
1695 struct bgp *bgp;
1696 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001697 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001698
1699 bgp = group->bgp;
1700
paul1eb8ef22005-04-07 07:30:20 +00001701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001702 {
1703 peer->group = NULL;
1704 peer_delete (peer);
1705 }
1706 list_delete (group->peer);
1707
1708 free (group->name);
1709 group->name = NULL;
1710
1711 group->conf->group = NULL;
1712 peer_delete (group->conf);
1713
1714 /* Delete from all peer_group list. */
1715 listnode_delete (bgp->group, group);
1716
1717 peer_group_free (group);
1718
1719 return 0;
1720}
1721
1722int
1723peer_group_remote_as_delete (struct peer_group *group)
1724{
1725 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001727
1728 if (! group->conf->as)
1729 return 0;
1730
paul1eb8ef22005-04-07 07:30:20 +00001731 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001732 {
1733 peer->group = NULL;
1734 peer_delete (peer);
1735 }
1736 list_delete_all_node (group->peer);
1737
1738 group->conf->as = 0;
1739
1740 return 0;
1741}
1742
1743/* Bind specified peer to peer group. */
1744int
1745peer_group_bind (struct bgp *bgp, union sockunion *su,
1746 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1747{
1748 struct peer *peer;
1749 int first_member = 0;
1750
1751 /* Check peer group's address family. */
1752 if (! group->conf->afc[afi][safi])
1753 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1754
1755 /* Lookup the peer. */
1756 peer = peer_lookup (bgp, su);
1757
1758 /* Create a new peer. */
1759 if (! peer)
1760 {
1761 if (! group->conf->as)
1762 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1763
1764 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1765 peer->group = group;
1766 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001767
Paul Jakmaca058a32006-09-14 02:58:49 +00001768 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001769 listnode_add (group->peer, peer);
1770 peer_group2peer_config_copy (group, peer, afi, safi);
1771
1772 return 0;
1773 }
1774
1775 /* When the peer already belongs to peer group, check the consistency. */
1776 if (peer->af_group[afi][safi])
1777 {
1778 if (strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1780
1781 return 0;
1782 }
1783
1784 /* Check current peer group configuration. */
1785 if (peer_group_active (peer)
1786 && strcmp (peer->group->name, group->name) != 0)
1787 return BGP_ERR_PEER_GROUP_MISMATCH;
1788
1789 if (! group->conf->as)
1790 {
1791 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1792 && peer_sort (group->conf) != peer_sort (peer))
1793 {
1794 if (as)
1795 *as = peer->as;
1796 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1797 }
1798
1799 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1800 first_member = 1;
1801 }
1802
1803 peer->af_group[afi][safi] = 1;
1804 peer->afc[afi][safi] = 1;
1805 if (! peer->group)
1806 {
1807 peer->group = group;
paul200df112005-06-01 11:17:05 +00001808
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001810 listnode_add (group->peer, peer);
1811 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 else
1813 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001814
1815 if (first_member)
1816 {
1817 /* Advertisement-interval reset */
1818 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1819 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1820 else
1821 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1822
1823 /* ebgp-multihop reset */
1824 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1825 group->conf->ttl = 255;
1826
1827 /* local-as reset */
1828 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1829 {
1830 group->conf->change_local_as = 0;
1831 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1832 }
1833 }
paulfee0f4c2004-09-13 05:12:46 +00001834
1835 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1836 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001837 struct listnode *pn;
1838
paulfee0f4c2004-09-13 05:12:46 +00001839 /* If it's not configured as RSERVER_CLIENT in any other address
1840 family, without being member of a peer_group, remove it from
1841 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001842 if (! peer_rsclient_active (peer)
1843 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001844 {
1845 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001846 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001847
1848 /* Clear our own rsclient rib for this afi/safi. */
1849 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001850 }
paulfee0f4c2004-09-13 05:12:46 +00001851
Paul Jakmab608d5b2008-07-02 02:12:07 +00001852 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001853
1854 /* Import policy. */
1855 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1856 {
1857 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1858 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1859 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1860 }
1861
1862 /* Export policy. */
1863 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1864 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1865 {
1866 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1867 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1868 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1869 }
1870 }
1871
paul718e3742002-12-13 20:15:29 +00001872 peer_group2peer_config_copy (group, peer, afi, safi);
1873
1874 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001875 {
1876 peer->last_reset = PEER_DOWN_RMAP_BIND;
1877 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1878 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1879 }
paul718e3742002-12-13 20:15:29 +00001880 else
1881 BGP_EVENT_ADD (peer, BGP_Stop);
1882
1883 return 0;
1884}
1885
1886int
1887peer_group_unbind (struct bgp *bgp, struct peer *peer,
1888 struct peer_group *group, afi_t afi, safi_t safi)
1889{
1890 if (! peer->af_group[afi][safi])
1891 return 0;
1892
1893 if (group != peer->group)
1894 return BGP_ERR_PEER_GROUP_MISMATCH;
1895
1896 peer->af_group[afi][safi] = 0;
1897 peer->afc[afi][safi] = 0;
1898 peer_af_flag_reset (peer, afi, safi);
1899
paulfee0f4c2004-09-13 05:12:46 +00001900 if (peer->rib[afi][safi])
1901 peer->rib[afi][safi] = NULL;
1902
paul718e3742002-12-13 20:15:29 +00001903 if (! peer_group_active (peer))
1904 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001905 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001906 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001907 listnode_delete (group->peer, peer);
1908 peer->group = NULL;
1909 if (group->conf->as)
1910 {
1911 peer_delete (peer);
1912 return 0;
1913 }
1914 peer_global_config_reset (peer);
1915 }
1916
1917 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001918 {
1919 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1920 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1921 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1922 }
paul718e3742002-12-13 20:15:29 +00001923 else
1924 BGP_EVENT_ADD (peer, BGP_Stop);
1925
1926 return 0;
1927}
1928
1929/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001930static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001931bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001932{
1933 struct bgp *bgp;
1934 afi_t afi;
1935 safi_t safi;
1936
paul200df112005-06-01 11:17:05 +00001937 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1938 return NULL;
1939
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001940 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001941 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001942 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001943
1944 bgp->peer = list_new ();
1945 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1946
1947 bgp->group = list_new ();
1948 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1949
paulfee0f4c2004-09-13 05:12:46 +00001950 bgp->rsclient = list_new ();
1951 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1952
paul718e3742002-12-13 20:15:29 +00001953 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1954 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1955 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001956 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1957 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1958 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001959 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1960 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001961 }
1962
1963 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1964 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1965 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001966 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1967 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001968
1969 bgp->as = *as;
1970
1971 if (name)
1972 bgp->name = strdup (name);
1973
1974 return bgp;
1975}
1976
1977/* Return first entry of BGP. */
1978struct bgp *
paul94f2b392005-06-28 12:44:16 +00001979bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001980{
1981 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001982 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001983 return NULL;
1984}
1985
1986/* Lookup BGP entry. */
1987struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001988bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001989{
1990 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001991 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001992
paul1eb8ef22005-04-07 07:30:20 +00001993 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001994 if (bgp->as == as
1995 && ((bgp->name == NULL && name == NULL)
1996 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1997 return bgp;
1998 return NULL;
1999}
2000
2001/* Lookup BGP structure by view name. */
2002struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002003bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002004{
2005 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002006 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002007
paul1eb8ef22005-04-07 07:30:20 +00002008 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002009 if ((bgp->name == NULL && name == NULL)
2010 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2011 return bgp;
2012 return NULL;
2013}
2014
2015/* Called from VTY commands. */
2016int
paulfd79ac92004-10-13 05:06:08 +00002017bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002018{
2019 struct bgp *bgp;
2020
2021 /* Multiple instance check. */
2022 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2023 {
2024 if (name)
2025 bgp = bgp_lookup_by_name (name);
2026 else
2027 bgp = bgp_get_default ();
2028
2029 /* Already exists. */
2030 if (bgp)
2031 {
2032 if (bgp->as != *as)
2033 {
2034 *as = bgp->as;
2035 return BGP_ERR_INSTANCE_MISMATCH;
2036 }
2037 *bgp_val = bgp;
2038 return 0;
2039 }
2040 }
2041 else
2042 {
2043 /* BGP instance name can not be specified for single instance. */
2044 if (name)
2045 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2046
2047 /* Get default BGP structure if exists. */
2048 bgp = bgp_get_default ();
2049
2050 if (bgp)
2051 {
2052 if (bgp->as != *as)
2053 {
2054 *as = bgp->as;
2055 return BGP_ERR_AS_MISMATCH;
2056 }
2057 *bgp_val = bgp;
2058 return 0;
2059 }
2060 }
2061
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002062 bgp = bgp_create (as, name);
2063 bgp_router_id_set(bgp, &router_id_zebra);
2064 *bgp_val = bgp;
2065
Paul Jakmaad12dde2012-06-13 22:50:07 +01002066 /* Create BGP server socket, if first instance. */
2067 if (list_isempty(bm->bgp))
2068 {
2069 if (bgp_socket (bm->port, bm->address) < 0)
2070 return BGP_ERR_INVALID_VALUE;
2071 }
2072
paul718e3742002-12-13 20:15:29 +00002073 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002074
2075 return 0;
2076}
2077
2078/* Delete BGP instance. */
2079int
2080bgp_delete (struct bgp *bgp)
2081{
2082 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002083 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002084 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002085 struct listnode *next;
2086 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002087 int i;
2088
2089 /* Delete static route. */
2090 bgp_static_delete (bgp);
2091
2092 /* Unset redistribution. */
2093 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2094 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2095 if (i != ZEBRA_ROUTE_BGP)
2096 bgp_redistribute_unset (bgp, afi, i);
2097
paul1eb8ef22005-04-07 07:30:20 +00002098 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2099 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002100
Chris Caputo228da422009-07-18 05:44:03 +00002101 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2102 peer_group_delete (group);
2103
2104 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002105
2106 if (bgp->peer_self) {
2107 peer_delete(bgp->peer_self);
2108 bgp->peer_self = NULL;
2109 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002110
2111 /* Remove visibility via the master list - there may however still be
2112 * routes to be processed still referencing the struct bgp.
2113 */
2114 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002115 if (list_isempty(bm->bgp))
2116 bgp_close ();
2117
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002118 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002119
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002120 return 0;
2121}
2122
2123static void bgp_free (struct bgp *);
2124
2125void
2126bgp_lock (struct bgp *bgp)
2127{
2128 ++bgp->lock;
2129}
2130
2131void
2132bgp_unlock(struct bgp *bgp)
2133{
Chris Caputo228da422009-07-18 05:44:03 +00002134 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002135 if (--bgp->lock == 0)
2136 bgp_free (bgp);
2137}
2138
2139static void
2140bgp_free (struct bgp *bgp)
2141{
2142 afi_t afi;
2143 safi_t safi;
2144
2145 list_delete (bgp->group);
2146 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002147 list_delete (bgp->rsclient);
2148
paul718e3742002-12-13 20:15:29 +00002149 if (bgp->name)
2150 free (bgp->name);
2151
2152 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2153 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2154 {
2155 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002156 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002157 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002158 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002159 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002160 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002161 }
2162 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002163}
2164
2165struct peer *
2166peer_lookup (struct bgp *bgp, union sockunion *su)
2167{
2168 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002169 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002170
Steve Hillfc4dc592009-07-28 17:54:35 +01002171 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002172 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2174 if (sockunion_same (&peer->su, su)
2175 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2176 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002177 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002178 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002179 {
2180 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002181
Paul Jakma2158ad22009-07-28 18:10:55 +01002182 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2183 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2184 if (sockunion_same (&peer->su, su)
2185 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2186 return peer;
paul718e3742002-12-13 20:15:29 +00002187 }
2188 return NULL;
2189}
2190
2191struct peer *
2192peer_lookup_with_open (union sockunion *su, as_t remote_as,
2193 struct in_addr *remote_id, int *as)
2194{
2195 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002196 struct listnode *node;
2197 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002198 struct bgp *bgp;
2199
Steve Hillfc4dc592009-07-28 17:54:35 +01002200 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002201 return NULL;
2202
Paul Jakma9d878772009-08-05 16:25:16 +01002203 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002204 {
Paul Jakma9d878772009-08-05 16:25:16 +01002205 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2206 {
2207 if (sockunion_same (&peer->su, su)
2208 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2209 {
2210 if (peer->as == remote_as
2211 && peer->remote_id.s_addr == remote_id->s_addr)
2212 return peer;
2213 if (peer->as == remote_as)
2214 *as = 1;
2215 }
2216 }
2217
2218 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2219 {
2220 if (sockunion_same (&peer->su, su)
2221 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2222 {
2223 if (peer->as == remote_as
2224 && peer->remote_id.s_addr == 0)
2225 return peer;
2226 if (peer->as == remote_as)
2227 *as = 1;
2228 }
2229 }
paul718e3742002-12-13 20:15:29 +00002230 }
2231 return NULL;
2232}
2233
2234/* If peer is configured at least one address family return 1. */
2235int
2236peer_active (struct peer *peer)
2237{
2238 if (peer->afc[AFI_IP][SAFI_UNICAST]
2239 || peer->afc[AFI_IP][SAFI_MULTICAST]
2240 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2241 || peer->afc[AFI_IP6][SAFI_UNICAST]
2242 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2243 return 1;
2244 return 0;
2245}
2246
2247/* If peer is negotiated at least one address family return 1. */
2248int
2249peer_active_nego (struct peer *peer)
2250{
2251 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2252 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2253 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2254 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2255 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2256 return 1;
2257 return 0;
2258}
2259
2260/* peer_flag_change_type. */
2261enum peer_change_type
2262{
2263 peer_change_none,
2264 peer_change_reset,
2265 peer_change_reset_in,
2266 peer_change_reset_out,
2267};
2268
paul94f2b392005-06-28 12:44:16 +00002269static void
paul718e3742002-12-13 20:15:29 +00002270peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2271 enum peer_change_type type)
2272{
2273 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2274 return;
2275
2276 if (type == peer_change_reset)
2277 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2278 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2279 else if (type == peer_change_reset_in)
2280 {
2281 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2282 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2283 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2284 else
2285 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2286 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2287 }
2288 else if (type == peer_change_reset_out)
2289 bgp_announce_route (peer, afi, safi);
2290}
2291
2292struct peer_flag_action
2293{
2294 /* Peer's flag. */
2295 u_int32_t flag;
2296
2297 /* This flag can be set for peer-group member. */
2298 u_char not_for_member;
2299
2300 /* Action when the flag is changed. */
2301 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002302
2303 /* Peer down cause */
2304 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002305};
2306
Stephen Hemminger03621952009-07-21 16:27:20 -07002307static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002308 {
2309 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2310 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2311 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2312 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2313 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002314 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002315 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002316 { 0, 0, 0 }
2317 };
2318
Stephen Hemminger03621952009-07-21 16:27:20 -07002319static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002320 {
2321 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2322 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2323 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2324 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2325 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2326 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2327 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2328 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2329 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2330 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2331 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2332 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2333 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002334 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002335 { 0, 0, 0 }
2336 };
2337
2338/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002339static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002340peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002341 struct peer_flag_action *action, u_int32_t flag)
2342{
2343 int i;
2344 int found = 0;
2345 int reset_in = 0;
2346 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002347 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002348
2349 /* Check peer's frag action. */
2350 for (i = 0; i < size; i++)
2351 {
2352 match = &action_list[i];
2353
2354 if (match->flag == 0)
2355 break;
2356
2357 if (match->flag & flag)
2358 {
2359 found = 1;
2360
2361 if (match->type == peer_change_reset_in)
2362 reset_in = 1;
2363 if (match->type == peer_change_reset_out)
2364 reset_out = 1;
2365 if (match->type == peer_change_reset)
2366 {
2367 reset_in = 1;
2368 reset_out = 1;
2369 }
2370 if (match->not_for_member)
2371 action->not_for_member = 1;
2372 }
2373 }
2374
2375 /* Set peer clear type. */
2376 if (reset_in && reset_out)
2377 action->type = peer_change_reset;
2378 else if (reset_in)
2379 action->type = peer_change_reset_in;
2380 else if (reset_out)
2381 action->type = peer_change_reset_out;
2382 else
2383 action->type = peer_change_none;
2384
2385 return found;
2386}
2387
paul94f2b392005-06-28 12:44:16 +00002388static void
paul718e3742002-12-13 20:15:29 +00002389peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2390{
2391 if (flag == PEER_FLAG_SHUTDOWN)
2392 {
2393 if (CHECK_FLAG (peer->flags, flag))
2394 {
hasso93406d82005-02-02 14:40:33 +00002395 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2396 peer_nsf_stop (peer);
2397
hasso0a486e52005-02-01 20:57:17 +00002398 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2399 if (peer->t_pmax_restart)
2400 {
2401 BGP_TIMER_OFF (peer->t_pmax_restart);
2402 if (BGP_DEBUG (events, EVENTS))
2403 zlog_debug ("%s Maximum-prefix restart timer canceled",
2404 peer->host);
2405 }
2406
hasso93406d82005-02-02 14:40:33 +00002407 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2408 peer_nsf_stop (peer);
2409
paul718e3742002-12-13 20:15:29 +00002410 if (peer->status == Established)
2411 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2412 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2413 else
2414 BGP_EVENT_ADD (peer, BGP_Stop);
2415 }
2416 else
2417 {
2418 peer->v_start = BGP_INIT_START_TIMER;
2419 BGP_EVENT_ADD (peer, BGP_Stop);
2420 }
2421 }
2422 else if (peer->status == Established)
2423 {
hassoc9502432005-02-01 22:01:48 +00002424 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2425 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2426 else if (flag == PEER_FLAG_PASSIVE)
2427 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002428 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002429 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002430
hassoc9502432005-02-01 22:01:48 +00002431 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2432 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002433 }
2434 else
2435 BGP_EVENT_ADD (peer, BGP_Stop);
2436}
2437
2438/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002439static int
paul718e3742002-12-13 20:15:29 +00002440peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2441{
2442 int found;
2443 int size;
2444 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002445 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002446 struct peer_flag_action action;
2447
2448 memset (&action, 0, sizeof (struct peer_flag_action));
2449 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2450
2451 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2452
2453 /* No flag action is found. */
2454 if (! found)
2455 return BGP_ERR_INVALID_FLAG;
2456
2457 /* Not for peer-group member. */
2458 if (action.not_for_member && peer_group_active (peer))
2459 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2460
2461 /* When unset the peer-group member's flag we have to check
2462 peer-group configuration. */
2463 if (! set && peer_group_active (peer))
2464 if (CHECK_FLAG (peer->group->conf->flags, flag))
2465 {
2466 if (flag == PEER_FLAG_SHUTDOWN)
2467 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2468 else
2469 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2470 }
2471
2472 /* Flag conflict check. */
2473 if (set
2474 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2475 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2476 return BGP_ERR_PEER_FLAG_CONFLICT;
2477
2478 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2479 {
2480 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2481 return 0;
2482 if (! set && ! CHECK_FLAG (peer->flags, flag))
2483 return 0;
2484 }
2485
2486 if (set)
2487 SET_FLAG (peer->flags, flag);
2488 else
2489 UNSET_FLAG (peer->flags, flag);
2490
2491 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2492 {
2493 if (action.type == peer_change_reset)
2494 peer_flag_modify_action (peer, flag);
2495
2496 return 0;
2497 }
2498
2499 /* peer-group member updates. */
2500 group = peer->group;
2501
paul1eb8ef22005-04-07 07:30:20 +00002502 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002503 {
2504 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2505 continue;
2506
2507 if (! set && ! CHECK_FLAG (peer->flags, flag))
2508 continue;
2509
2510 if (set)
2511 SET_FLAG (peer->flags, flag);
2512 else
2513 UNSET_FLAG (peer->flags, flag);
2514
2515 if (action.type == peer_change_reset)
2516 peer_flag_modify_action (peer, flag);
2517 }
2518 return 0;
2519}
2520
2521int
2522peer_flag_set (struct peer *peer, u_int32_t flag)
2523{
2524 return peer_flag_modify (peer, flag, 1);
2525}
2526
2527int
2528peer_flag_unset (struct peer *peer, u_int32_t flag)
2529{
2530 return peer_flag_modify (peer, flag, 0);
2531}
2532
paul94f2b392005-06-28 12:44:16 +00002533static int
paul718e3742002-12-13 20:15:29 +00002534peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2535{
2536 if (peer->af_group[afi][safi])
2537 return 1;
2538 return 0;
2539}
2540
paul94f2b392005-06-28 12:44:16 +00002541static int
paul718e3742002-12-13 20:15:29 +00002542peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2543 int set)
2544{
2545 int found;
2546 int size;
paul1eb8ef22005-04-07 07:30:20 +00002547 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002548 struct peer_group *group;
2549 struct peer_flag_action action;
2550
2551 memset (&action, 0, sizeof (struct peer_flag_action));
2552 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2553
2554 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2555
2556 /* No flag action is found. */
2557 if (! found)
2558 return BGP_ERR_INVALID_FLAG;
2559
2560 /* Adress family must be activated. */
2561 if (! peer->afc[afi][safi])
2562 return BGP_ERR_PEER_INACTIVE;
2563
2564 /* Not for peer-group member. */
2565 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2566 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2567
2568 /* Spcecial check for reflector client. */
2569 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2570 && peer_sort (peer) != BGP_PEER_IBGP)
2571 return BGP_ERR_NOT_INTERNAL_PEER;
2572
2573 /* Spcecial check for remove-private-AS. */
2574 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2575 && peer_sort (peer) == BGP_PEER_IBGP)
2576 return BGP_ERR_REMOVE_PRIVATE_AS;
2577
2578 /* When unset the peer-group member's flag we have to check
2579 peer-group configuration. */
2580 if (! set && peer->af_group[afi][safi])
2581 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2582 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2583
2584 /* When current flag configuration is same as requested one. */
2585 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2586 {
2587 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2588 return 0;
2589 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2590 return 0;
2591 }
2592
2593 if (set)
2594 SET_FLAG (peer->af_flags[afi][safi], flag);
2595 else
2596 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2597
2598 /* Execute action when peer is established. */
2599 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2600 && peer->status == Established)
2601 {
2602 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2603 bgp_clear_adj_in (peer, afi, safi);
2604 else
hassoe0701b72004-05-20 09:19:34 +00002605 {
2606 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2607 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2608 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2609 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2610 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2611 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2612 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2613 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2614
2615 peer_change_action (peer, afi, safi, action.type);
2616 }
2617
paul718e3742002-12-13 20:15:29 +00002618 }
2619
2620 /* Peer group member updates. */
2621 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2622 {
2623 group = peer->group;
2624
paul1eb8ef22005-04-07 07:30:20 +00002625 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002626 {
2627 if (! peer->af_group[afi][safi])
2628 continue;
2629
2630 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2631 continue;
2632
2633 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2634 continue;
2635
2636 if (set)
2637 SET_FLAG (peer->af_flags[afi][safi], flag);
2638 else
2639 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2640
2641 if (peer->status == Established)
2642 {
2643 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2644 bgp_clear_adj_in (peer, afi, safi);
2645 else
hassoe0701b72004-05-20 09:19:34 +00002646 {
2647 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2648 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2649 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2650 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2651 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2652 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2653 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2654 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2655
2656 peer_change_action (peer, afi, safi, action.type);
2657 }
paul718e3742002-12-13 20:15:29 +00002658 }
2659 }
2660 }
2661 return 0;
2662}
2663
2664int
2665peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2666{
2667 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2668}
2669
2670int
2671peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2672{
2673 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2674}
2675
2676/* EBGP multihop configuration. */
2677int
2678peer_ebgp_multihop_set (struct peer *peer, int ttl)
2679{
2680 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002681 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002682 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002683
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002684 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002685 return 0;
2686
Nick Hilliardfa411a22011-03-23 15:33:17 +00002687 /* see comment in peer_ttl_security_hops_set() */
2688 if (ttl != MAXTTL)
2689 {
2690 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2691 {
2692 group = peer->group;
2693 if (group->conf->gtsm_hops != 0)
2694 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2695
2696 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2697 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002698 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002699 continue;
2700
2701 if (peer1->gtsm_hops != 0)
2702 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2703 }
2704 }
2705 else
2706 {
2707 if (peer->gtsm_hops != 0)
2708 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2709 }
2710 }
2711
paul718e3742002-12-13 20:15:29 +00002712 peer->ttl = ttl;
2713
2714 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2715 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002716 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002717 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002718 }
2719 else
2720 {
2721 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002722 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002723 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002724 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002725 continue;
paul718e3742002-12-13 20:15:29 +00002726
pauleb821182004-05-01 08:44:08 +00002727 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002728
pauleb821182004-05-01 08:44:08 +00002729 if (peer->fd >= 0)
2730 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2731 }
paul718e3742002-12-13 20:15:29 +00002732 }
2733 return 0;
2734}
2735
2736int
2737peer_ebgp_multihop_unset (struct peer *peer)
2738{
2739 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002740 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002741
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002742 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002743 return 0;
2744
Nick Hilliardfa411a22011-03-23 15:33:17 +00002745 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2746 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2747
paul718e3742002-12-13 20:15:29 +00002748 if (peer_group_active (peer))
2749 peer->ttl = peer->group->conf->ttl;
2750 else
2751 peer->ttl = 1;
2752
2753 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2754 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002755 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002756 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002757 }
2758 else
2759 {
2760 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002761 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002762 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002763 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002764 continue;
paul718e3742002-12-13 20:15:29 +00002765
pauleb821182004-05-01 08:44:08 +00002766 peer->ttl = 1;
2767
2768 if (peer->fd >= 0)
2769 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2770 }
paul718e3742002-12-13 20:15:29 +00002771 }
2772 return 0;
2773}
2774
2775/* Neighbor description. */
2776int
2777peer_description_set (struct peer *peer, char *desc)
2778{
2779 if (peer->desc)
2780 XFREE (MTYPE_PEER_DESC, peer->desc);
2781
2782 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2783
2784 return 0;
2785}
2786
2787int
2788peer_description_unset (struct peer *peer)
2789{
2790 if (peer->desc)
2791 XFREE (MTYPE_PEER_DESC, peer->desc);
2792
2793 peer->desc = NULL;
2794
2795 return 0;
2796}
2797
2798/* Neighbor update-source. */
2799int
paulfd79ac92004-10-13 05:06:08 +00002800peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002801{
2802 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002803 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002804
2805 if (peer->update_if)
2806 {
2807 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2808 && strcmp (peer->update_if, ifname) == 0)
2809 return 0;
2810
2811 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2812 peer->update_if = NULL;
2813 }
2814
2815 if (peer->update_source)
2816 {
2817 sockunion_free (peer->update_source);
2818 peer->update_source = NULL;
2819 }
2820
2821 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2822
2823 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2824 {
2825 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002826 {
2827 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2828 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2829 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2830 }
paul718e3742002-12-13 20:15:29 +00002831 else
2832 BGP_EVENT_ADD (peer, BGP_Stop);
2833 return 0;
2834 }
2835
2836 /* peer-group member updates. */
2837 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002838 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002839 {
2840 if (peer->update_if)
2841 {
2842 if (strcmp (peer->update_if, ifname) == 0)
2843 continue;
2844
2845 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2846 peer->update_if = NULL;
2847 }
2848
2849 if (peer->update_source)
2850 {
2851 sockunion_free (peer->update_source);
2852 peer->update_source = NULL;
2853 }
2854
2855 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2856
2857 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002858 {
2859 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2860 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2861 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2862 }
paul718e3742002-12-13 20:15:29 +00002863 else
2864 BGP_EVENT_ADD (peer, BGP_Stop);
2865 }
2866 return 0;
2867}
2868
2869int
2870peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2871{
2872 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002873 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002874
2875 if (peer->update_source)
2876 {
2877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2878 && sockunion_cmp (peer->update_source, su) == 0)
2879 return 0;
2880 sockunion_free (peer->update_source);
2881 peer->update_source = NULL;
2882 }
2883
2884 if (peer->update_if)
2885 {
2886 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2887 peer->update_if = NULL;
2888 }
2889
2890 peer->update_source = sockunion_dup (su);
2891
2892 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2893 {
2894 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002895 {
2896 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2897 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2898 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2899 }
paul718e3742002-12-13 20:15:29 +00002900 else
2901 BGP_EVENT_ADD (peer, BGP_Stop);
2902 return 0;
2903 }
2904
2905 /* peer-group member updates. */
2906 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002907 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002908 {
2909 if (peer->update_source)
2910 {
2911 if (sockunion_cmp (peer->update_source, su) == 0)
2912 continue;
2913 sockunion_free (peer->update_source);
2914 peer->update_source = NULL;
2915 }
2916
2917 if (peer->update_if)
2918 {
2919 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2920 peer->update_if = NULL;
2921 }
2922
2923 peer->update_source = sockunion_dup (su);
2924
2925 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002926 {
2927 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2928 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2929 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2930 }
paul718e3742002-12-13 20:15:29 +00002931 else
2932 BGP_EVENT_ADD (peer, BGP_Stop);
2933 }
2934 return 0;
2935}
2936
2937int
2938peer_update_source_unset (struct peer *peer)
2939{
2940 union sockunion *su;
2941 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002942 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002943
2944 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2945 && ! peer->update_source
2946 && ! peer->update_if)
2947 return 0;
2948
2949 if (peer->update_source)
2950 {
2951 sockunion_free (peer->update_source);
2952 peer->update_source = NULL;
2953 }
2954 if (peer->update_if)
2955 {
2956 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2957 peer->update_if = NULL;
2958 }
2959
2960 if (peer_group_active (peer))
2961 {
2962 group = peer->group;
2963
2964 if (group->conf->update_source)
2965 {
2966 su = sockunion_dup (group->conf->update_source);
2967 peer->update_source = su;
2968 }
2969 else if (group->conf->update_if)
2970 peer->update_if =
2971 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2972 }
2973
2974 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2975 {
2976 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002977 {
2978 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2979 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2980 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2981 }
paul718e3742002-12-13 20:15:29 +00002982 else
2983 BGP_EVENT_ADD (peer, BGP_Stop);
2984 return 0;
2985 }
2986
2987 /* peer-group member updates. */
2988 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002989 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002990 {
2991 if (! peer->update_source && ! peer->update_if)
2992 continue;
2993
2994 if (peer->update_source)
2995 {
2996 sockunion_free (peer->update_source);
2997 peer->update_source = NULL;
2998 }
2999
3000 if (peer->update_if)
3001 {
3002 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3003 peer->update_if = NULL;
3004 }
3005
3006 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003007 {
3008 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3009 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3010 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3011 }
paul718e3742002-12-13 20:15:29 +00003012 else
3013 BGP_EVENT_ADD (peer, BGP_Stop);
3014 }
3015 return 0;
3016}
3017
3018int
3019peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003020 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003021{
3022 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003023 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003024
3025 /* Adress family must be activated. */
3026 if (! peer->afc[afi][safi])
3027 return BGP_ERR_PEER_INACTIVE;
3028
3029 /* Default originate can't be used for peer group memeber. */
3030 if (peer_is_group_member (peer, afi, safi))
3031 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3032
3033 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3034 || (rmap && ! peer->default_rmap[afi][safi].name)
3035 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3036 {
3037 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3038
3039 if (rmap)
3040 {
3041 if (peer->default_rmap[afi][safi].name)
3042 free (peer->default_rmap[afi][safi].name);
3043 peer->default_rmap[afi][safi].name = strdup (rmap);
3044 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3045 }
3046 }
3047
3048 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3049 {
3050 if (peer->status == Established && peer->afc_nego[afi][safi])
3051 bgp_default_originate (peer, afi, safi, 0);
3052 return 0;
3053 }
3054
3055 /* peer-group member updates. */
3056 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003057 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003058 {
3059 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3060
3061 if (rmap)
3062 {
3063 if (peer->default_rmap[afi][safi].name)
3064 free (peer->default_rmap[afi][safi].name);
3065 peer->default_rmap[afi][safi].name = strdup (rmap);
3066 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3067 }
3068
3069 if (peer->status == Established && peer->afc_nego[afi][safi])
3070 bgp_default_originate (peer, afi, safi, 0);
3071 }
3072 return 0;
3073}
3074
3075int
3076peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3077{
3078 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003079 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003080
3081 /* Adress family must be activated. */
3082 if (! peer->afc[afi][safi])
3083 return BGP_ERR_PEER_INACTIVE;
3084
3085 /* Default originate can't be used for peer group memeber. */
3086 if (peer_is_group_member (peer, afi, safi))
3087 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3088
3089 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3090 {
3091 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3092
3093 if (peer->default_rmap[afi][safi].name)
3094 free (peer->default_rmap[afi][safi].name);
3095 peer->default_rmap[afi][safi].name = NULL;
3096 peer->default_rmap[afi][safi].map = NULL;
3097 }
3098
3099 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3100 {
3101 if (peer->status == Established && peer->afc_nego[afi][safi])
3102 bgp_default_originate (peer, afi, safi, 1);
3103 return 0;
3104 }
3105
3106 /* peer-group member updates. */
3107 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003108 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003109 {
3110 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3111
3112 if (peer->default_rmap[afi][safi].name)
3113 free (peer->default_rmap[afi][safi].name);
3114 peer->default_rmap[afi][safi].name = NULL;
3115 peer->default_rmap[afi][safi].map = NULL;
3116
3117 if (peer->status == Established && peer->afc_nego[afi][safi])
3118 bgp_default_originate (peer, afi, safi, 1);
3119 }
3120 return 0;
3121}
3122
3123int
3124peer_port_set (struct peer *peer, u_int16_t port)
3125{
3126 peer->port = port;
3127 return 0;
3128}
3129
3130int
3131peer_port_unset (struct peer *peer)
3132{
3133 peer->port = BGP_PORT_DEFAULT;
3134 return 0;
3135}
3136
3137/* neighbor weight. */
3138int
3139peer_weight_set (struct peer *peer, u_int16_t weight)
3140{
3141 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003142 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003143
3144 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3145 peer->weight = weight;
3146
3147 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3148 return 0;
3149
3150 /* peer-group member updates. */
3151 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003152 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003153 {
3154 peer->weight = group->conf->weight;
3155 }
3156 return 0;
3157}
3158
3159int
3160peer_weight_unset (struct peer *peer)
3161{
3162 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003163 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003164
3165 /* Set default weight. */
3166 if (peer_group_active (peer))
3167 peer->weight = peer->group->conf->weight;
3168 else
3169 peer->weight = 0;
3170
3171 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3172
3173 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3174 return 0;
3175
3176 /* peer-group member updates. */
3177 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003178 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003179 {
3180 peer->weight = 0;
3181 }
3182 return 0;
3183}
3184
3185int
3186peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3187{
3188 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003189 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003190
3191 /* Not for peer group memeber. */
3192 if (peer_group_active (peer))
3193 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3194
3195 /* keepalive value check. */
3196 if (keepalive > 65535)
3197 return BGP_ERR_INVALID_VALUE;
3198
3199 /* Holdtime value check. */
3200 if (holdtime > 65535)
3201 return BGP_ERR_INVALID_VALUE;
3202
3203 /* Holdtime value must be either 0 or greater than 3. */
3204 if (holdtime < 3 && holdtime != 0)
3205 return BGP_ERR_INVALID_VALUE;
3206
3207 /* Set value to the configuration. */
3208 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3209 peer->holdtime = holdtime;
3210 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3211
3212 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3213 return 0;
3214
3215 /* peer-group member updates. */
3216 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003217 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003218 {
3219 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3220 peer->holdtime = group->conf->holdtime;
3221 peer->keepalive = group->conf->keepalive;
3222 }
3223 return 0;
3224}
3225
3226int
3227peer_timers_unset (struct peer *peer)
3228{
3229 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003230 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003231
3232 if (peer_group_active (peer))
3233 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3234
3235 /* Clear configuration. */
3236 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3237 peer->keepalive = 0;
3238 peer->holdtime = 0;
3239
3240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3241 return 0;
3242
3243 /* peer-group member updates. */
3244 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003245 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003246 {
3247 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3248 peer->holdtime = 0;
3249 peer->keepalive = 0;
3250 }
3251
3252 return 0;
3253}
3254
3255int
3256peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3257{
3258 if (peer_group_active (peer))
3259 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3260
3261 if (connect > 65535)
3262 return BGP_ERR_INVALID_VALUE;
3263
3264 /* Set value to the configuration. */
3265 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3266 peer->connect = connect;
3267
3268 /* Set value to timer setting. */
3269 peer->v_connect = connect;
3270
3271 return 0;
3272}
3273
3274int
3275peer_timers_connect_unset (struct peer *peer)
3276{
3277 if (peer_group_active (peer))
3278 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3279
3280 /* Clear configuration. */
3281 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3282 peer->connect = 0;
3283
3284 /* Set timer setting to default value. */
3285 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3286
3287 return 0;
3288}
3289
3290int
3291peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3292{
3293 if (peer_group_active (peer))
3294 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3295
3296 if (routeadv > 600)
3297 return BGP_ERR_INVALID_VALUE;
3298
3299 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3300 peer->routeadv = routeadv;
3301 peer->v_routeadv = routeadv;
3302
3303 return 0;
3304}
3305
3306int
3307peer_advertise_interval_unset (struct peer *peer)
3308{
3309 if (peer_group_active (peer))
3310 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3311
3312 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3313 peer->routeadv = 0;
3314
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003315 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003316 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3317 else
3318 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3319
3320 return 0;
3321}
3322
paul718e3742002-12-13 20:15:29 +00003323/* neighbor interface */
3324int
paulfd79ac92004-10-13 05:06:08 +00003325peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003326{
3327 if (peer->ifname)
3328 free (peer->ifname);
3329 peer->ifname = strdup (str);
3330
3331 return 0;
3332}
3333
3334int
3335peer_interface_unset (struct peer *peer)
3336{
3337 if (peer->ifname)
3338 free (peer->ifname);
3339 peer->ifname = NULL;
3340
3341 return 0;
3342}
3343
3344/* Allow-as in. */
3345int
3346peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3347{
3348 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003349 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003350
3351 if (allow_num < 1 || allow_num > 10)
3352 return BGP_ERR_INVALID_VALUE;
3353
3354 if (peer->allowas_in[afi][safi] != allow_num)
3355 {
3356 peer->allowas_in[afi][safi] = allow_num;
3357 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3358 peer_change_action (peer, afi, safi, peer_change_reset_in);
3359 }
3360
3361 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3362 return 0;
3363
3364 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003365 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003366 {
3367 if (peer->allowas_in[afi][safi] != allow_num)
3368 {
3369 peer->allowas_in[afi][safi] = allow_num;
3370 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3371 peer_change_action (peer, afi, safi, peer_change_reset_in);
3372 }
3373
3374 }
3375 return 0;
3376}
3377
3378int
3379peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3380{
3381 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003382 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003383
3384 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3385 {
3386 peer->allowas_in[afi][safi] = 0;
3387 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3388 }
3389
3390 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3391 return 0;
3392
3393 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003394 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003395 {
3396 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3397 {
3398 peer->allowas_in[afi][safi] = 0;
3399 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3400 }
3401 }
3402 return 0;
3403}
3404
3405int
3406peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3407{
3408 struct bgp *bgp = peer->bgp;
3409 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003410 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003411
3412 if (peer_sort (peer) != BGP_PEER_EBGP
3413 && peer_sort (peer) != BGP_PEER_INTERNAL)
3414 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3415
3416 if (bgp->as == as)
3417 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3418
3419 if (peer_group_active (peer))
3420 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3421
3422 if (peer->change_local_as == as &&
3423 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3424 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3425 return 0;
3426
3427 peer->change_local_as = as;
3428 if (no_prepend)
3429 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3430 else
3431 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3432
3433 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3434 {
3435 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003436 {
3437 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3438 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3439 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3440 }
paul718e3742002-12-13 20:15:29 +00003441 else
3442 BGP_EVENT_ADD (peer, BGP_Stop);
3443
3444 return 0;
3445 }
3446
3447 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003448 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003449 {
3450 peer->change_local_as = as;
3451 if (no_prepend)
3452 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3453 else
3454 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3455
3456 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003457 {
3458 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3459 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3460 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3461 }
paul718e3742002-12-13 20:15:29 +00003462 else
3463 BGP_EVENT_ADD (peer, BGP_Stop);
3464 }
3465
3466 return 0;
3467}
3468
3469int
3470peer_local_as_unset (struct peer *peer)
3471{
3472 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003473 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003474
3475 if (peer_group_active (peer))
3476 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3477
3478 if (! peer->change_local_as)
3479 return 0;
3480
3481 peer->change_local_as = 0;
3482 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3483
3484 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3485 {
3486 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003487 {
3488 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3489 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3490 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3491 }
paul718e3742002-12-13 20:15:29 +00003492 else
3493 BGP_EVENT_ADD (peer, BGP_Stop);
3494
3495 return 0;
3496 }
3497
3498 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003499 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003500 {
3501 peer->change_local_as = 0;
3502 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3503
3504 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003505 {
3506 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3507 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3508 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3509 }
paul718e3742002-12-13 20:15:29 +00003510 else
3511 BGP_EVENT_ADD (peer, BGP_Stop);
3512 }
3513 return 0;
3514}
3515
Paul Jakma0df7c912008-07-21 21:02:49 +00003516/* Set password for authenticating with the peer. */
3517int
3518peer_password_set (struct peer *peer, const char *password)
3519{
3520 struct listnode *nn, *nnode;
3521 int len = password ? strlen(password) : 0;
3522 int ret = BGP_SUCCESS;
3523
3524 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3525 return BGP_ERR_INVALID_VALUE;
3526
3527 if (peer->password && strcmp (peer->password, password) == 0
3528 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3529 return 0;
3530
3531 if (peer->password)
3532 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3533
3534 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3535
3536 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3537 {
3538 if (peer->status == Established)
3539 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3540 else
3541 BGP_EVENT_ADD (peer, BGP_Stop);
3542
3543 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3544 }
3545
3546 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3547 {
3548 if (peer->password && strcmp (peer->password, password) == 0)
3549 continue;
3550
3551 if (peer->password)
3552 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3553
3554 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3555
3556 if (peer->status == Established)
3557 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3558 else
3559 BGP_EVENT_ADD (peer, BGP_Stop);
3560
3561 if (bgp_md5_set (peer) < 0)
3562 ret = BGP_ERR_TCPSIG_FAILED;
3563 }
3564
3565 return ret;
3566}
3567
3568int
3569peer_password_unset (struct peer *peer)
3570{
3571 struct listnode *nn, *nnode;
3572
3573 if (!peer->password
3574 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3575 return 0;
3576
3577 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3578 {
3579 if (peer_group_active (peer)
3580 && peer->group->conf->password
3581 && strcmp (peer->group->conf->password, peer->password) == 0)
3582 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3583
3584 if (peer->status == Established)
3585 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3586 else
3587 BGP_EVENT_ADD (peer, BGP_Stop);
3588
3589 if (peer->password)
3590 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3591
3592 peer->password = NULL;
3593
3594 bgp_md5_set (peer);
3595
3596 return 0;
3597 }
3598
3599 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3600 peer->password = NULL;
3601
3602 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3603 {
3604 if (!peer->password)
3605 continue;
3606
3607 if (peer->status == Established)
3608 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3609 else
3610 BGP_EVENT_ADD (peer, BGP_Stop);
3611
3612 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3613 peer->password = NULL;
3614
3615 bgp_md5_set (peer);
3616 }
3617
3618 return 0;
3619}
3620
paul718e3742002-12-13 20:15:29 +00003621/* Set distribute list to the peer. */
3622int
3623peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003624 const char *name)
paul718e3742002-12-13 20:15:29 +00003625{
3626 struct bgp_filter *filter;
3627 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003628 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003629
3630 if (! peer->afc[afi][safi])
3631 return BGP_ERR_PEER_INACTIVE;
3632
3633 if (direct != FILTER_IN && direct != FILTER_OUT)
3634 return BGP_ERR_INVALID_VALUE;
3635
3636 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3637 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3638
3639 filter = &peer->filter[afi][safi];
3640
3641 if (filter->plist[direct].name)
3642 return BGP_ERR_PEER_FILTER_CONFLICT;
3643
3644 if (filter->dlist[direct].name)
3645 free (filter->dlist[direct].name);
3646 filter->dlist[direct].name = strdup (name);
3647 filter->dlist[direct].alist = access_list_lookup (afi, name);
3648
3649 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3650 return 0;
3651
3652 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003653 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003654 {
3655 filter = &peer->filter[afi][safi];
3656
3657 if (! peer->af_group[afi][safi])
3658 continue;
3659
3660 if (filter->dlist[direct].name)
3661 free (filter->dlist[direct].name);
3662 filter->dlist[direct].name = strdup (name);
3663 filter->dlist[direct].alist = access_list_lookup (afi, name);
3664 }
3665
3666 return 0;
3667}
3668
3669int
3670peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3671{
3672 struct bgp_filter *filter;
3673 struct bgp_filter *gfilter;
3674 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003675 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003676
3677 if (! peer->afc[afi][safi])
3678 return BGP_ERR_PEER_INACTIVE;
3679
3680 if (direct != FILTER_IN && direct != FILTER_OUT)
3681 return BGP_ERR_INVALID_VALUE;
3682
3683 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3684 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3685
3686 filter = &peer->filter[afi][safi];
3687
3688 /* apply peer-group filter */
3689 if (peer->af_group[afi][safi])
3690 {
3691 gfilter = &peer->group->conf->filter[afi][safi];
3692
3693 if (gfilter->dlist[direct].name)
3694 {
3695 if (filter->dlist[direct].name)
3696 free (filter->dlist[direct].name);
3697 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3698 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3699 return 0;
3700 }
3701 }
3702
3703 if (filter->dlist[direct].name)
3704 free (filter->dlist[direct].name);
3705 filter->dlist[direct].name = NULL;
3706 filter->dlist[direct].alist = NULL;
3707
3708 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3709 return 0;
3710
3711 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003712 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003713 {
3714 filter = &peer->filter[afi][safi];
3715
3716 if (! peer->af_group[afi][safi])
3717 continue;
3718
3719 if (filter->dlist[direct].name)
3720 free (filter->dlist[direct].name);
3721 filter->dlist[direct].name = NULL;
3722 filter->dlist[direct].alist = NULL;
3723 }
3724
3725 return 0;
3726}
3727
3728/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003729static void
paul718e3742002-12-13 20:15:29 +00003730peer_distribute_update (struct access_list *access)
3731{
3732 afi_t afi;
3733 safi_t safi;
3734 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003735 struct listnode *mnode, *mnnode;
3736 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003737 struct bgp *bgp;
3738 struct peer *peer;
3739 struct peer_group *group;
3740 struct bgp_filter *filter;
3741
paul1eb8ef22005-04-07 07:30:20 +00003742 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003743 {
paul1eb8ef22005-04-07 07:30:20 +00003744 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003745 {
3746 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3747 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3748 {
3749 filter = &peer->filter[afi][safi];
3750
3751 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3752 {
3753 if (filter->dlist[direct].name)
3754 filter->dlist[direct].alist =
3755 access_list_lookup (afi, filter->dlist[direct].name);
3756 else
3757 filter->dlist[direct].alist = NULL;
3758 }
3759 }
3760 }
paul1eb8ef22005-04-07 07:30:20 +00003761 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003762 {
3763 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3764 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3765 {
3766 filter = &group->conf->filter[afi][safi];
3767
3768 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3769 {
3770 if (filter->dlist[direct].name)
3771 filter->dlist[direct].alist =
3772 access_list_lookup (afi, filter->dlist[direct].name);
3773 else
3774 filter->dlist[direct].alist = NULL;
3775 }
3776 }
3777 }
3778 }
3779}
3780
3781/* Set prefix list to the peer. */
3782int
3783peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003784 const char *name)
paul718e3742002-12-13 20:15:29 +00003785{
3786 struct bgp_filter *filter;
3787 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003788 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003789
3790 if (! peer->afc[afi][safi])
3791 return BGP_ERR_PEER_INACTIVE;
3792
3793 if (direct != FILTER_IN && direct != FILTER_OUT)
3794 return BGP_ERR_INVALID_VALUE;
3795
3796 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3797 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3798
3799 filter = &peer->filter[afi][safi];
3800
3801 if (filter->dlist[direct].name)
3802 return BGP_ERR_PEER_FILTER_CONFLICT;
3803
3804 if (filter->plist[direct].name)
3805 free (filter->plist[direct].name);
3806 filter->plist[direct].name = strdup (name);
3807 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3808
3809 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3810 return 0;
3811
3812 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003813 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003814 {
3815 filter = &peer->filter[afi][safi];
3816
3817 if (! peer->af_group[afi][safi])
3818 continue;
3819
3820 if (filter->plist[direct].name)
3821 free (filter->plist[direct].name);
3822 filter->plist[direct].name = strdup (name);
3823 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3824 }
3825 return 0;
3826}
3827
3828int
3829peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3830{
3831 struct bgp_filter *filter;
3832 struct bgp_filter *gfilter;
3833 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003834 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003835
3836 if (! peer->afc[afi][safi])
3837 return BGP_ERR_PEER_INACTIVE;
3838
3839 if (direct != FILTER_IN && direct != FILTER_OUT)
3840 return BGP_ERR_INVALID_VALUE;
3841
3842 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3843 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3844
3845 filter = &peer->filter[afi][safi];
3846
3847 /* apply peer-group filter */
3848 if (peer->af_group[afi][safi])
3849 {
3850 gfilter = &peer->group->conf->filter[afi][safi];
3851
3852 if (gfilter->plist[direct].name)
3853 {
3854 if (filter->plist[direct].name)
3855 free (filter->plist[direct].name);
3856 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3857 filter->plist[direct].plist = gfilter->plist[direct].plist;
3858 return 0;
3859 }
3860 }
3861
3862 if (filter->plist[direct].name)
3863 free (filter->plist[direct].name);
3864 filter->plist[direct].name = NULL;
3865 filter->plist[direct].plist = NULL;
3866
3867 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3868 return 0;
3869
3870 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003871 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003872 {
3873 filter = &peer->filter[afi][safi];
3874
3875 if (! peer->af_group[afi][safi])
3876 continue;
3877
3878 if (filter->plist[direct].name)
3879 free (filter->plist[direct].name);
3880 filter->plist[direct].name = NULL;
3881 filter->plist[direct].plist = NULL;
3882 }
3883
3884 return 0;
3885}
3886
3887/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003888static void
paul718e3742002-12-13 20:15:29 +00003889peer_prefix_list_update (struct prefix_list *plist)
3890{
paul1eb8ef22005-04-07 07:30:20 +00003891 struct listnode *mnode, *mnnode;
3892 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003893 struct bgp *bgp;
3894 struct peer *peer;
3895 struct peer_group *group;
3896 struct bgp_filter *filter;
3897 afi_t afi;
3898 safi_t safi;
3899 int direct;
3900
paul1eb8ef22005-04-07 07:30:20 +00003901 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003902 {
paul1eb8ef22005-04-07 07:30:20 +00003903 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003904 {
3905 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3906 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3907 {
3908 filter = &peer->filter[afi][safi];
3909
3910 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3911 {
3912 if (filter->plist[direct].name)
3913 filter->plist[direct].plist =
3914 prefix_list_lookup (afi, filter->plist[direct].name);
3915 else
3916 filter->plist[direct].plist = NULL;
3917 }
3918 }
3919 }
paul1eb8ef22005-04-07 07:30:20 +00003920 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003921 {
3922 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3923 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3924 {
3925 filter = &group->conf->filter[afi][safi];
3926
3927 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3928 {
3929 if (filter->plist[direct].name)
3930 filter->plist[direct].plist =
3931 prefix_list_lookup (afi, filter->plist[direct].name);
3932 else
3933 filter->plist[direct].plist = NULL;
3934 }
3935 }
3936 }
3937 }
3938}
3939
3940int
3941peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003942 const char *name)
paul718e3742002-12-13 20:15:29 +00003943{
3944 struct bgp_filter *filter;
3945 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003946 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003947
3948 if (! peer->afc[afi][safi])
3949 return BGP_ERR_PEER_INACTIVE;
3950
3951 if (direct != FILTER_IN && direct != FILTER_OUT)
3952 return BGP_ERR_INVALID_VALUE;
3953
3954 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3955 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3956
3957 filter = &peer->filter[afi][safi];
3958
3959 if (filter->aslist[direct].name)
3960 free (filter->aslist[direct].name);
3961 filter->aslist[direct].name = strdup (name);
3962 filter->aslist[direct].aslist = as_list_lookup (name);
3963
3964 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3965 return 0;
3966
3967 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003968 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003969 {
3970 filter = &peer->filter[afi][safi];
3971
3972 if (! peer->af_group[afi][safi])
3973 continue;
3974
3975 if (filter->aslist[direct].name)
3976 free (filter->aslist[direct].name);
3977 filter->aslist[direct].name = strdup (name);
3978 filter->aslist[direct].aslist = as_list_lookup (name);
3979 }
3980 return 0;
3981}
3982
3983int
3984peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3985{
3986 struct bgp_filter *filter;
3987 struct bgp_filter *gfilter;
3988 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003989 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003990
3991 if (! peer->afc[afi][safi])
3992 return BGP_ERR_PEER_INACTIVE;
3993
hassob5f29602005-05-25 21:00:28 +00003994 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003995 return BGP_ERR_INVALID_VALUE;
3996
hassob5f29602005-05-25 21:00:28 +00003997 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003998 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3999
4000 filter = &peer->filter[afi][safi];
4001
4002 /* apply peer-group filter */
4003 if (peer->af_group[afi][safi])
4004 {
4005 gfilter = &peer->group->conf->filter[afi][safi];
4006
4007 if (gfilter->aslist[direct].name)
4008 {
4009 if (filter->aslist[direct].name)
4010 free (filter->aslist[direct].name);
4011 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4012 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4013 return 0;
4014 }
4015 }
4016
4017 if (filter->aslist[direct].name)
4018 free (filter->aslist[direct].name);
4019 filter->aslist[direct].name = NULL;
4020 filter->aslist[direct].aslist = NULL;
4021
4022 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4023 return 0;
4024
4025 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004026 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004027 {
4028 filter = &peer->filter[afi][safi];
4029
4030 if (! peer->af_group[afi][safi])
4031 continue;
4032
4033 if (filter->aslist[direct].name)
4034 free (filter->aslist[direct].name);
4035 filter->aslist[direct].name = NULL;
4036 filter->aslist[direct].aslist = NULL;
4037 }
4038
4039 return 0;
4040}
4041
paul94f2b392005-06-28 12:44:16 +00004042static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004043peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004044{
4045 afi_t afi;
4046 safi_t safi;
4047 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004048 struct listnode *mnode, *mnnode;
4049 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004050 struct bgp *bgp;
4051 struct peer *peer;
4052 struct peer_group *group;
4053 struct bgp_filter *filter;
4054
paul1eb8ef22005-04-07 07:30:20 +00004055 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004056 {
paul1eb8ef22005-04-07 07:30:20 +00004057 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004058 {
4059 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4060 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4061 {
4062 filter = &peer->filter[afi][safi];
4063
4064 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4065 {
4066 if (filter->aslist[direct].name)
4067 filter->aslist[direct].aslist =
4068 as_list_lookup (filter->aslist[direct].name);
4069 else
4070 filter->aslist[direct].aslist = NULL;
4071 }
4072 }
4073 }
paul1eb8ef22005-04-07 07:30:20 +00004074 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004075 {
4076 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4077 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4078 {
4079 filter = &group->conf->filter[afi][safi];
4080
4081 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4082 {
4083 if (filter->aslist[direct].name)
4084 filter->aslist[direct].aslist =
4085 as_list_lookup (filter->aslist[direct].name);
4086 else
4087 filter->aslist[direct].aslist = NULL;
4088 }
4089 }
4090 }
4091 }
4092}
4093
4094/* Set route-map to the peer. */
4095int
4096peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004097 const char *name)
paul718e3742002-12-13 20:15:29 +00004098{
4099 struct bgp_filter *filter;
4100 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004101 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004102
4103 if (! peer->afc[afi][safi])
4104 return BGP_ERR_PEER_INACTIVE;
4105
paulfee0f4c2004-09-13 05:12:46 +00004106 if (direct != RMAP_IN && direct != RMAP_OUT &&
4107 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004108 return BGP_ERR_INVALID_VALUE;
4109
paulfee0f4c2004-09-13 05:12:46 +00004110 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4111 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004112 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4113
4114 filter = &peer->filter[afi][safi];
4115
4116 if (filter->map[direct].name)
4117 free (filter->map[direct].name);
4118
4119 filter->map[direct].name = strdup (name);
4120 filter->map[direct].map = route_map_lookup_by_name (name);
4121
4122 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4123 return 0;
4124
4125 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004126 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004127 {
4128 filter = &peer->filter[afi][safi];
4129
4130 if (! peer->af_group[afi][safi])
4131 continue;
4132
4133 if (filter->map[direct].name)
4134 free (filter->map[direct].name);
4135 filter->map[direct].name = strdup (name);
4136 filter->map[direct].map = route_map_lookup_by_name (name);
4137 }
4138 return 0;
4139}
4140
4141/* Unset route-map from the peer. */
4142int
4143peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4144{
4145 struct bgp_filter *filter;
4146 struct bgp_filter *gfilter;
4147 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004148 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004149
4150 if (! peer->afc[afi][safi])
4151 return BGP_ERR_PEER_INACTIVE;
4152
hassob5f29602005-05-25 21:00:28 +00004153 if (direct != RMAP_IN && direct != RMAP_OUT &&
4154 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004155 return BGP_ERR_INVALID_VALUE;
4156
hassob5f29602005-05-25 21:00:28 +00004157 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4158 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004159 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4160
4161 filter = &peer->filter[afi][safi];
4162
4163 /* apply peer-group filter */
4164 if (peer->af_group[afi][safi])
4165 {
4166 gfilter = &peer->group->conf->filter[afi][safi];
4167
4168 if (gfilter->map[direct].name)
4169 {
4170 if (filter->map[direct].name)
4171 free (filter->map[direct].name);
4172 filter->map[direct].name = strdup (gfilter->map[direct].name);
4173 filter->map[direct].map = gfilter->map[direct].map;
4174 return 0;
4175 }
4176 }
4177
4178 if (filter->map[direct].name)
4179 free (filter->map[direct].name);
4180 filter->map[direct].name = NULL;
4181 filter->map[direct].map = NULL;
4182
4183 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4184 return 0;
4185
4186 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004187 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004188 {
4189 filter = &peer->filter[afi][safi];
4190
4191 if (! peer->af_group[afi][safi])
4192 continue;
4193
4194 if (filter->map[direct].name)
4195 free (filter->map[direct].name);
4196 filter->map[direct].name = NULL;
4197 filter->map[direct].map = NULL;
4198 }
4199 return 0;
4200}
4201
4202/* Set unsuppress-map to the peer. */
4203int
paulfd79ac92004-10-13 05:06:08 +00004204peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4205 const char *name)
paul718e3742002-12-13 20:15:29 +00004206{
4207 struct bgp_filter *filter;
4208 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004209 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004210
4211 if (! peer->afc[afi][safi])
4212 return BGP_ERR_PEER_INACTIVE;
4213
4214 if (peer_is_group_member (peer, afi, safi))
4215 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4216
4217 filter = &peer->filter[afi][safi];
4218
4219 if (filter->usmap.name)
4220 free (filter->usmap.name);
4221
4222 filter->usmap.name = strdup (name);
4223 filter->usmap.map = route_map_lookup_by_name (name);
4224
4225 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4226 return 0;
4227
4228 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004229 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004230 {
4231 filter = &peer->filter[afi][safi];
4232
4233 if (! peer->af_group[afi][safi])
4234 continue;
4235
4236 if (filter->usmap.name)
4237 free (filter->usmap.name);
4238 filter->usmap.name = strdup (name);
4239 filter->usmap.map = route_map_lookup_by_name (name);
4240 }
4241 return 0;
4242}
4243
4244/* Unset route-map from the peer. */
4245int
4246peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4247{
4248 struct bgp_filter *filter;
4249 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004250 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004251
4252 if (! peer->afc[afi][safi])
4253 return BGP_ERR_PEER_INACTIVE;
4254
4255 if (peer_is_group_member (peer, afi, safi))
4256 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4257
4258 filter = &peer->filter[afi][safi];
4259
4260 if (filter->usmap.name)
4261 free (filter->usmap.name);
4262 filter->usmap.name = NULL;
4263 filter->usmap.map = NULL;
4264
4265 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4266 return 0;
4267
4268 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004269 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004270 {
4271 filter = &peer->filter[afi][safi];
4272
4273 if (! peer->af_group[afi][safi])
4274 continue;
4275
4276 if (filter->usmap.name)
4277 free (filter->usmap.name);
4278 filter->usmap.name = NULL;
4279 filter->usmap.map = NULL;
4280 }
4281 return 0;
4282}
4283
4284int
4285peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004286 u_int32_t max, u_char threshold,
4287 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004288{
4289 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004290 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004291
4292 if (! peer->afc[afi][safi])
4293 return BGP_ERR_PEER_INACTIVE;
4294
4295 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4296 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004297 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004298 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004299 if (warning)
4300 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4301 else
4302 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4303
4304 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4305 return 0;
4306
4307 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004308 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004309 {
4310 if (! peer->af_group[afi][safi])
4311 continue;
4312
4313 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4314 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004315 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004316 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004317 if (warning)
4318 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4319 else
4320 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4321 }
4322 return 0;
4323}
4324
4325int
4326peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4327{
4328 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004329 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004330
4331 if (! peer->afc[afi][safi])
4332 return BGP_ERR_PEER_INACTIVE;
4333
4334 /* apply peer-group config */
4335 if (peer->af_group[afi][safi])
4336 {
4337 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4338 PEER_FLAG_MAX_PREFIX))
4339 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4340 else
4341 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4342
4343 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4344 PEER_FLAG_MAX_PREFIX_WARNING))
4345 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4346 else
4347 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4348
4349 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004350 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004351 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004352 return 0;
4353 }
4354
4355 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4356 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4357 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004358 peer->pmax_threshold[afi][safi] = 0;
4359 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004360
4361 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4362 return 0;
4363
4364 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004365 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004366 {
4367 if (! peer->af_group[afi][safi])
4368 continue;
4369
4370 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4371 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4372 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004373 peer->pmax_threshold[afi][safi] = 0;
4374 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004375 }
4376 return 0;
4377}
4378
Nick Hilliardfa411a22011-03-23 15:33:17 +00004379/* Set # of hops between us and BGP peer. */
4380int
4381peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4382{
4383 struct peer_group *group;
4384 struct listnode *node, *nnode;
4385 struct peer *peer1;
4386 int ret;
4387
4388 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4389
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004390 if (peer->sort == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004391 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004392
4393 /* We cannot configure ttl-security hops when ebgp-multihop is already
4394 set. For non peer-groups, the check is simple. For peer-groups, it's
4395 slightly messy, because we need to check both the peer-group structure
4396 and all peer-group members for any trace of ebgp-multihop configuration
4397 before actually applying the ttl-security rules. Cisco really made a
4398 mess of this configuration parameter, and OpenBGPD got it right.
4399 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004400
4401 if (peer->gtsm_hops == 0) {
4402 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4403 {
4404 group = peer->group;
4405 if (group->conf->ttl != 1)
4406 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004407
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004408 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4409 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004410 if (peer1->sort == BGP_PEER_IBGP)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004411 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004412
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004413 if (peer1->ttl != 1)
4414 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4415 }
4416 }
4417 else
4418 {
4419 if (peer->ttl != 1)
4420 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4421 }
4422 /* specify MAXTTL on outgoing packets */
4423 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4424 if (ret != 0)
4425 return ret;
4426 }
4427
Nick Hilliardfa411a22011-03-23 15:33:17 +00004428 peer->gtsm_hops = gtsm_hops;
4429
Nick Hilliardfa411a22011-03-23 15:33:17 +00004430 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4431 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004432 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004433 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4434 }
4435 else
4436 {
4437 group = peer->group;
4438 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4439 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004440 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004441 continue;
4442
4443 peer->gtsm_hops = group->conf->gtsm_hops;
4444
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004445 /* Change setting of existing peer
4446 * established then change value (may break connectivity)
4447 * not established yet (teardown session and restart)
4448 * no session then do nothing (will get handled by next connection)
4449 */
4450 if (peer->status == Established)
4451 {
4452 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4453 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4454 MAXTTL + 1 - peer->gtsm_hops);
4455 }
4456 else if (peer->status < Established)
4457 {
4458 if (BGP_DEBUG (events, EVENTS))
4459 zlog_debug ("%s Min-ttl changed", peer->host);
4460 BGP_EVENT_ADD (peer, BGP_Stop);
4461 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004462 }
4463 }
4464
4465 return 0;
4466}
4467
4468int
4469peer_ttl_security_hops_unset (struct peer *peer)
4470{
4471 struct peer_group *group;
4472 struct listnode *node, *nnode;
4473 struct peer *opeer;
4474
4475 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4476
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004477 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004478 return 0;
4479
4480 /* if a peer-group member, then reset to peer-group default rather than 0 */
4481 if (peer_group_active (peer))
4482 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4483 else
4484 peer->gtsm_hops = 0;
4485
4486 opeer = peer;
4487 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4488 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004489 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004490 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4491 }
4492 else
4493 {
4494 group = peer->group;
4495 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4496 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004497 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004498 continue;
4499
4500 peer->gtsm_hops = 0;
4501
4502 if (peer->fd >= 0)
4503 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4504 }
4505 }
4506
4507 return peer_ebgp_multihop_unset (opeer);
4508}
4509
paul718e3742002-12-13 20:15:29 +00004510int
4511peer_clear (struct peer *peer)
4512{
4513 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4514 {
hasso0a486e52005-02-01 20:57:17 +00004515 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4516 {
4517 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4518 if (peer->t_pmax_restart)
4519 {
4520 BGP_TIMER_OFF (peer->t_pmax_restart);
4521 if (BGP_DEBUG (events, EVENTS))
4522 zlog_debug ("%s Maximum-prefix restart timer canceled",
4523 peer->host);
4524 }
4525 BGP_EVENT_ADD (peer, BGP_Start);
4526 return 0;
4527 }
4528
paul718e3742002-12-13 20:15:29 +00004529 peer->v_start = BGP_INIT_START_TIMER;
4530 if (peer->status == Established)
4531 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4532 BGP_NOTIFY_CEASE_ADMIN_RESET);
4533 else
4534 BGP_EVENT_ADD (peer, BGP_Stop);
4535 }
4536 return 0;
4537}
4538
4539int
4540peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4541 enum bgp_clear_type stype)
4542{
4543 if (peer->status != Established)
4544 return 0;
4545
4546 if (! peer->afc[afi][safi])
4547 return BGP_ERR_AF_UNCONFIGURED;
4548
paulfee0f4c2004-09-13 05:12:46 +00004549 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4550 {
4551 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4552 return 0;
4553 bgp_check_local_routes_rsclient (peer, afi, safi);
4554 bgp_soft_reconfig_rsclient (peer, afi, safi);
4555 }
4556
paul718e3742002-12-13 20:15:29 +00004557 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4558 bgp_announce_route (peer, afi, safi);
4559
4560 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4561 {
4562 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4563 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4564 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4565 {
4566 struct bgp_filter *filter = &peer->filter[afi][safi];
4567 u_char prefix_type;
4568
4569 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4570 prefix_type = ORF_TYPE_PREFIX;
4571 else
4572 prefix_type = ORF_TYPE_PREFIX_OLD;
4573
4574 if (filter->plist[FILTER_IN].plist)
4575 {
4576 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4577 bgp_route_refresh_send (peer, afi, safi,
4578 prefix_type, REFRESH_DEFER, 1);
4579 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4580 REFRESH_IMMEDIATE, 0);
4581 }
4582 else
4583 {
4584 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4585 bgp_route_refresh_send (peer, afi, safi,
4586 prefix_type, REFRESH_IMMEDIATE, 1);
4587 else
4588 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4589 }
4590 return 0;
4591 }
4592 }
4593
4594 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4595 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4596 {
4597 /* If neighbor has soft reconfiguration inbound flag.
4598 Use Adj-RIB-In database. */
4599 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4600 bgp_soft_reconfig_in (peer, afi, safi);
4601 else
4602 {
4603 /* If neighbor has route refresh capability, send route refresh
4604 message to the peer. */
4605 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4606 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4607 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4608 else
4609 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4610 }
4611 }
4612 return 0;
4613}
4614
paulfd79ac92004-10-13 05:06:08 +00004615/* Display peer uptime.*/
4616/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004617char *
4618peer_uptime (time_t uptime2, char *buf, size_t len)
4619{
4620 time_t uptime1;
4621 struct tm *tm;
4622
4623 /* Check buffer length. */
4624 if (len < BGP_UPTIME_LEN)
4625 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004626 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004627 /* XXX: should return status instead of buf... */
4628 snprintf (buf, len, "<error> ");
4629 return buf;
paul718e3742002-12-13 20:15:29 +00004630 }
4631
4632 /* If there is no connection has been done before print `never'. */
4633 if (uptime2 == 0)
4634 {
4635 snprintf (buf, len, "never ");
4636 return buf;
4637 }
4638
4639 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004640 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004641 uptime1 -= uptime2;
4642 tm = gmtime (&uptime1);
4643
4644 /* Making formatted timer strings. */
4645#define ONE_DAY_SECOND 60*60*24
4646#define ONE_WEEK_SECOND 60*60*24*7
4647
4648 if (uptime1 < ONE_DAY_SECOND)
4649 snprintf (buf, len, "%02d:%02d:%02d",
4650 tm->tm_hour, tm->tm_min, tm->tm_sec);
4651 else if (uptime1 < ONE_WEEK_SECOND)
4652 snprintf (buf, len, "%dd%02dh%02dm",
4653 tm->tm_yday, tm->tm_hour, tm->tm_min);
4654 else
4655 snprintf (buf, len, "%02dw%dd%02dh",
4656 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4657 return buf;
4658}
4659
paul94f2b392005-06-28 12:44:16 +00004660static void
paul718e3742002-12-13 20:15:29 +00004661bgp_config_write_filter (struct vty *vty, struct peer *peer,
4662 afi_t afi, safi_t safi)
4663{
4664 struct bgp_filter *filter;
4665 struct bgp_filter *gfilter = NULL;
4666 char *addr;
4667 int in = FILTER_IN;
4668 int out = FILTER_OUT;
4669
4670 addr = peer->host;
4671 filter = &peer->filter[afi][safi];
4672 if (peer->af_group[afi][safi])
4673 gfilter = &peer->group->conf->filter[afi][safi];
4674
4675 /* distribute-list. */
4676 if (filter->dlist[in].name)
4677 if (! gfilter || ! gfilter->dlist[in].name
4678 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4679 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4680 filter->dlist[in].name, VTY_NEWLINE);
4681 if (filter->dlist[out].name && ! gfilter)
4682 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4683 filter->dlist[out].name, VTY_NEWLINE);
4684
4685 /* prefix-list. */
4686 if (filter->plist[in].name)
4687 if (! gfilter || ! gfilter->plist[in].name
4688 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4689 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4690 filter->plist[in].name, VTY_NEWLINE);
4691 if (filter->plist[out].name && ! gfilter)
4692 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4693 filter->plist[out].name, VTY_NEWLINE);
4694
4695 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004696 if (filter->map[RMAP_IN].name)
4697 if (! gfilter || ! gfilter->map[RMAP_IN].name
4698 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004699 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004700 filter->map[RMAP_IN].name, VTY_NEWLINE);
4701 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004702 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004703 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4704 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4705 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4706 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4707 if (filter->map[RMAP_EXPORT].name)
4708 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4709 || strcmp (filter->map[RMAP_EXPORT].name,
4710 gfilter->map[RMAP_EXPORT].name) != 0)
4711 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4712 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004713
4714 /* unsuppress-map */
4715 if (filter->usmap.name && ! gfilter)
4716 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4717 filter->usmap.name, VTY_NEWLINE);
4718
4719 /* filter-list. */
4720 if (filter->aslist[in].name)
4721 if (! gfilter || ! gfilter->aslist[in].name
4722 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4723 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4724 filter->aslist[in].name, VTY_NEWLINE);
4725 if (filter->aslist[out].name && ! gfilter)
4726 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4727 filter->aslist[out].name, VTY_NEWLINE);
4728}
4729
4730/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004731static void
paul718e3742002-12-13 20:15:29 +00004732bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4733 struct peer *peer, afi_t afi, safi_t safi)
4734{
paul718e3742002-12-13 20:15:29 +00004735 struct peer *g_peer = NULL;
4736 char buf[SU_ADDRSTRLEN];
4737 char *addr;
4738
paul718e3742002-12-13 20:15:29 +00004739 addr = peer->host;
4740 if (peer_group_active (peer))
4741 g_peer = peer->group->conf;
4742
4743 /************************************
4744 ****** Global to the neighbor ******
4745 ************************************/
4746 if (afi == AFI_IP && safi == SAFI_UNICAST)
4747 {
4748 /* remote-as. */
4749 if (! peer_group_active (peer))
4750 {
4751 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4752 vty_out (vty, " neighbor %s peer-group%s", addr,
4753 VTY_NEWLINE);
4754 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004755 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004756 VTY_NEWLINE);
4757 }
4758 else
4759 {
4760 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004761 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004762 VTY_NEWLINE);
4763 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4764 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4765 peer->group->name, VTY_NEWLINE);
4766 }
4767
4768 /* local-as. */
4769 if (peer->change_local_as)
4770 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004771 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004772 peer->change_local_as,
4773 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4774 " no-prepend" : "", VTY_NEWLINE);
4775
4776 /* Description. */
4777 if (peer->desc)
4778 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4779 VTY_NEWLINE);
4780
4781 /* Shutdown. */
4782 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4783 if (! peer_group_active (peer) ||
4784 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4785 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4786
Paul Jakma0df7c912008-07-21 21:02:49 +00004787 /* Password. */
4788 if (peer->password)
4789 if (!peer_group_active (peer)
4790 || ! g_peer->password
4791 || strcmp (peer->password, g_peer->password) != 0)
4792 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4793 VTY_NEWLINE);
4794
paul718e3742002-12-13 20:15:29 +00004795 /* BGP port. */
4796 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004797 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004798 VTY_NEWLINE);
4799
4800 /* Local interface name. */
4801 if (peer->ifname)
4802 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4803 VTY_NEWLINE);
4804
4805 /* Passive. */
4806 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4807 if (! peer_group_active (peer) ||
4808 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4809 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4810
4811 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004812 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004813 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004814 if (! peer_group_active (peer) ||
4815 g_peer->ttl != peer->ttl)
4816 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4817 VTY_NEWLINE);
4818
Nick Hilliardfa411a22011-03-23 15:33:17 +00004819 /* ttl-security hops */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004820 if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004821 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004822 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004823 peer->gtsm_hops, VTY_NEWLINE);
4824
hasso6ffd2072005-02-02 14:50:11 +00004825 /* disable-connected-check. */
4826 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004827 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004828 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4829 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004830
4831 /* Update-source. */
4832 if (peer->update_if)
4833 if (! peer_group_active (peer) || ! g_peer->update_if
4834 || strcmp (g_peer->update_if, peer->update_if) != 0)
4835 vty_out (vty, " neighbor %s update-source %s%s", addr,
4836 peer->update_if, VTY_NEWLINE);
4837 if (peer->update_source)
4838 if (! peer_group_active (peer) || ! g_peer->update_source
4839 || sockunion_cmp (g_peer->update_source,
4840 peer->update_source) != 0)
4841 vty_out (vty, " neighbor %s update-source %s%s", addr,
4842 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4843 VTY_NEWLINE);
4844
paul718e3742002-12-13 20:15:29 +00004845 /* advertisement-interval */
4846 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4847 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4848 addr, peer->v_routeadv, VTY_NEWLINE);
4849
4850 /* timers. */
4851 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4852 && ! peer_group_active (peer))
4853 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4854 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4855
4856 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4857 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4858 peer->connect, VTY_NEWLINE);
4859
4860 /* Default weight. */
4861 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4862 if (! peer_group_active (peer) ||
4863 g_peer->weight != peer->weight)
4864 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4865 VTY_NEWLINE);
4866
paul718e3742002-12-13 20:15:29 +00004867 /* Dynamic capability. */
4868 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4869 if (! peer_group_active (peer) ||
4870 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4871 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4872 VTY_NEWLINE);
4873
4874 /* dont capability negotiation. */
4875 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4876 if (! peer_group_active (peer) ||
4877 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4878 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4879 VTY_NEWLINE);
4880
4881 /* override capability negotiation. */
4882 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4883 if (! peer_group_active (peer) ||
4884 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4885 vty_out (vty, " neighbor %s override-capability%s", addr,
4886 VTY_NEWLINE);
4887
4888 /* strict capability negotiation. */
4889 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4890 if (! peer_group_active (peer) ||
4891 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4892 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4893 VTY_NEWLINE);
4894
4895 if (! peer_group_active (peer))
4896 {
4897 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4898 {
4899 if (peer->afc[AFI_IP][SAFI_UNICAST])
4900 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4901 }
4902 else
4903 {
4904 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4905 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4906 }
4907 }
4908 }
4909
4910
4911 /************************************
4912 ****** Per AF to the neighbor ******
4913 ************************************/
4914
4915 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4916 {
4917 if (peer->af_group[afi][safi])
4918 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4919 peer->group->name, VTY_NEWLINE);
4920 else
4921 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4922 }
4923
4924 /* ORF capability. */
4925 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4926 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4927 if (! peer->af_group[afi][safi])
4928 {
4929 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4930
4931 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4932 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4933 vty_out (vty, " both");
4934 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4935 vty_out (vty, " send");
4936 else
4937 vty_out (vty, " receive");
4938 vty_out (vty, "%s", VTY_NEWLINE);
4939 }
4940
4941 /* Route reflector client. */
4942 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4943 && ! peer->af_group[afi][safi])
4944 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4945 VTY_NEWLINE);
4946
4947 /* Nexthop self. */
4948 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4949 && ! peer->af_group[afi][safi])
4950 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4951
4952 /* Remove private AS. */
4953 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4954 && ! peer->af_group[afi][safi])
4955 vty_out (vty, " neighbor %s remove-private-AS%s",
4956 addr, VTY_NEWLINE);
4957
4958 /* send-community print. */
4959 if (! peer->af_group[afi][safi])
4960 {
4961 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
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, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4966 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4967 vty_out (vty, " neighbor %s send-community extended%s",
4968 addr, VTY_NEWLINE);
4969 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4970 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4971 }
4972 else
4973 {
4974 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4975 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4976 vty_out (vty, " no neighbor %s send-community both%s",
4977 addr, VTY_NEWLINE);
4978 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4979 vty_out (vty, " no neighbor %s send-community extended%s",
4980 addr, VTY_NEWLINE);
4981 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4982 vty_out (vty, " no neighbor %s send-community%s",
4983 addr, VTY_NEWLINE);
4984 }
4985 }
4986
4987 /* Default information */
4988 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4989 && ! peer->af_group[afi][safi])
4990 {
4991 vty_out (vty, " neighbor %s default-originate", addr);
4992 if (peer->default_rmap[afi][safi].name)
4993 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4994 vty_out (vty, "%s", VTY_NEWLINE);
4995 }
4996
4997 /* Soft reconfiguration inbound. */
4998 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4999 if (! peer->af_group[afi][safi] ||
5000 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5001 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5002 VTY_NEWLINE);
5003
5004 /* maximum-prefix. */
5005 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5006 if (! peer->af_group[afi][safi]
5007 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005008 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005009 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5010 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005011 {
hasso0a486e52005-02-01 20:57:17 +00005012 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5013 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5014 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5015 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5016 vty_out (vty, " warning-only");
5017 if (peer->pmax_restart[afi][safi])
5018 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5019 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005020 }
paul718e3742002-12-13 20:15:29 +00005021
5022 /* Route server client. */
5023 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5024 && ! peer->af_group[afi][safi])
5025 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5026
Dylan Hall3cf12882011-10-27 15:28:17 +04005027 /* Nexthop-local unchanged. */
5028 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5029 && ! peer->af_group[afi][safi])
5030 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5031
paul718e3742002-12-13 20:15:29 +00005032 /* Allow AS in. */
5033 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5034 if (! peer_group_active (peer)
5035 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5036 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5037 {
5038 if (peer->allowas_in[afi][safi] == 3)
5039 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5040 else
5041 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5042 peer->allowas_in[afi][safi], VTY_NEWLINE);
5043 }
5044
5045 /* Filter. */
5046 bgp_config_write_filter (vty, peer, afi, safi);
5047
5048 /* atribute-unchanged. */
5049 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5050 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5051 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5052 && ! peer->af_group[afi][safi])
5053 {
5054 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5055 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5056 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5057 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5058 else
5059 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5060 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5061 " as-path" : "",
5062 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5063 " next-hop" : "",
5064 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5065 " med" : "", VTY_NEWLINE);
5066 }
5067}
5068
5069/* Display "address-family" configuration header. */
5070void
5071bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5072 int *write)
5073{
5074 if (*write)
5075 return;
5076
5077 if (afi == AFI_IP && safi == SAFI_UNICAST)
5078 return;
5079
5080 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5081
5082 if (afi == AFI_IP)
5083 {
5084 if (safi == SAFI_MULTICAST)
5085 vty_out (vty, "ipv4 multicast");
5086 else if (safi == SAFI_MPLS_VPN)
5087 vty_out (vty, "vpnv4 unicast");
5088 }
5089 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005090 {
5091 vty_out (vty, "ipv6");
5092
5093 if (safi == SAFI_MULTICAST)
5094 vty_out (vty, " multicast");
5095 }
paul718e3742002-12-13 20:15:29 +00005096
5097 vty_out (vty, "%s", VTY_NEWLINE);
5098
5099 *write = 1;
5100}
5101
5102/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005103static int
paul718e3742002-12-13 20:15:29 +00005104bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5105 safi_t safi)
5106{
5107 int write = 0;
5108 struct peer *peer;
5109 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005110 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005111
5112 bgp_config_write_network (vty, bgp, afi, safi, &write);
5113
5114 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5115
paul1eb8ef22005-04-07 07:30:20 +00005116 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005117 {
5118 if (group->conf->afc[afi][safi])
5119 {
5120 bgp_config_write_family_header (vty, afi, safi, &write);
5121 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5122 }
5123 }
paul1eb8ef22005-04-07 07:30:20 +00005124 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005125 {
5126 if (peer->afc[afi][safi])
5127 {
5128 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5129 {
5130 bgp_config_write_family_header (vty, afi, safi, &write);
5131 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5132 }
5133 }
5134 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005135
5136 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5137
paul718e3742002-12-13 20:15:29 +00005138 if (write)
5139 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5140
5141 return write;
5142}
5143
5144int
5145bgp_config_write (struct vty *vty)
5146{
5147 int write = 0;
5148 struct bgp *bgp;
5149 struct peer_group *group;
5150 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005151 struct listnode *node, *nnode;
5152 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005153
5154 /* BGP Multiple instance. */
5155 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5156 {
5157 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5158 write++;
5159 }
5160
5161 /* BGP Config type. */
5162 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5163 {
5164 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5165 write++;
5166 }
5167
5168 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005169 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005170 {
5171 if (write)
5172 vty_out (vty, "!%s", VTY_NEWLINE);
5173
5174 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005175 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005176
5177 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5178 {
5179 if (bgp->name)
5180 vty_out (vty, " view %s", bgp->name);
5181 }
5182 vty_out (vty, "%s", VTY_NEWLINE);
5183
5184 /* No Synchronization */
5185 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5186 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5187
5188 /* BGP fast-external-failover. */
5189 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5190 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5191
5192 /* BGP router ID. */
5193 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5194 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5195 VTY_NEWLINE);
5196
paul848973c2003-08-13 00:32:49 +00005197 /* BGP log-neighbor-changes. */
5198 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5199 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5200
paul718e3742002-12-13 20:15:29 +00005201 /* BGP configuration. */
5202 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5203 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5204
5205 /* BGP default ipv4-unicast. */
5206 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5207 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5208
5209 /* BGP default local-preference. */
5210 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5211 vty_out (vty, " bgp default local-preference %d%s",
5212 bgp->default_local_pref, VTY_NEWLINE);
5213
5214 /* BGP client-to-client reflection. */
5215 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5216 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5217
5218 /* BGP cluster ID. */
5219 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5220 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5221 VTY_NEWLINE);
5222
hassoe0701b72004-05-20 09:19:34 +00005223 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005224 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005225 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5226 VTY_NEWLINE);
5227
5228 /* Confederation peer */
5229 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005230 {
hassoe0701b72004-05-20 09:19:34 +00005231 int i;
paul718e3742002-12-13 20:15:29 +00005232
hassoe0701b72004-05-20 09:19:34 +00005233 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005234
hassoe0701b72004-05-20 09:19:34 +00005235 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005236 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005237
hassoe0701b72004-05-20 09:19:34 +00005238 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005239 }
5240
5241 /* BGP enforce-first-as. */
5242 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5243 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5244
5245 /* BGP deterministic-med. */
5246 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5247 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005248
5249 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005250 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5251 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5252 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005253 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5254 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5255
paul718e3742002-12-13 20:15:29 +00005256 /* BGP bestpath method. */
5257 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5258 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005259 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5260 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005261 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5262 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5263 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5264 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5265 {
5266 vty_out (vty, " bgp bestpath med");
5267 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5268 vty_out (vty, " confed");
5269 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5270 vty_out (vty, " missing-as-worst");
5271 vty_out (vty, "%s", VTY_NEWLINE);
5272 }
5273
5274 /* BGP network import check. */
5275 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5276 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5277
5278 /* BGP scan interval. */
5279 bgp_config_write_scan_time (vty);
5280
5281 /* BGP flag dampening. */
5282 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5283 BGP_CONFIG_DAMPENING))
5284 bgp_config_write_damp (vty);
5285
5286 /* BGP static route configuration. */
5287 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5288
5289 /* BGP redistribute configuration. */
5290 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5291
5292 /* BGP timers configuration. */
5293 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5294 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5295 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5296 bgp->default_holdtime, VTY_NEWLINE);
5297
5298 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005299 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005300 {
5301 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5302 }
5303
5304 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005305 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005306 {
5307 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5308 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5309 }
5310
Josh Bailey165b5ff2011-07-20 20:43:22 -07005311 /* maximum-paths */
5312 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5313
paul718e3742002-12-13 20:15:29 +00005314 /* Distance configuration. */
5315 bgp_config_write_distance (vty, bgp);
5316
5317 /* No auto-summary */
5318 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5319 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5320
5321 /* IPv4 multicast configuration. */
5322 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5323
5324 /* IPv4 VPN configuration. */
5325 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5326
5327 /* IPv6 unicast configuration. */
5328 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5329
Paul Jakma37a217a2007-04-10 19:20:29 +00005330 /* IPv6 multicast configuration. */
5331 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5332
paul718e3742002-12-13 20:15:29 +00005333 write++;
5334 }
5335 return write;
5336}
5337
5338void
paul94f2b392005-06-28 12:44:16 +00005339bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005340{
5341 memset (&bgp_master, 0, sizeof (struct bgp_master));
5342
5343 bm = &bgp_master;
5344 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005345 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005346 bm->port = BGP_PORT_DEFAULT;
5347 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005348 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005349}
paul200df112005-06-01 11:17:05 +00005350
paul718e3742002-12-13 20:15:29 +00005351
5352void
paul94f2b392005-06-28 12:44:16 +00005353bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005354{
paul718e3742002-12-13 20:15:29 +00005355 /* BGP VTY commands installation. */
5356 bgp_vty_init ();
5357
paul718e3742002-12-13 20:15:29 +00005358 /* Init zebra. */
5359 bgp_zebra_init ();
5360
5361 /* BGP inits. */
5362 bgp_attr_init ();
5363 bgp_debug_init ();
5364 bgp_dump_init ();
5365 bgp_route_init ();
5366 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005367 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005368 bgp_scan_init ();
5369 bgp_mplsvpn_init ();
5370
5371 /* Access list initialize. */
5372 access_list_init ();
5373 access_list_add_hook (peer_distribute_update);
5374 access_list_delete_hook (peer_distribute_update);
5375
5376 /* Filter list initialize. */
5377 bgp_filter_init ();
5378 as_list_add_hook (peer_aslist_update);
5379 as_list_delete_hook (peer_aslist_update);
5380
5381 /* Prefix list initialize.*/
5382 prefix_list_init ();
5383 prefix_list_add_hook (peer_prefix_list_update);
5384 prefix_list_delete_hook (peer_prefix_list_update);
5385
5386 /* Community list initialize. */
5387 bgp_clist = community_list_init ();
5388
5389#ifdef HAVE_SNMP
5390 bgp_snmp_init ();
5391#endif /* HAVE_SNMP */
5392}
paul545acaf2004-04-20 15:13:15 +00005393
5394void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005395bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005396{
paul545acaf2004-04-20 15:13:15 +00005397 struct bgp *bgp;
5398 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005399 struct listnode *node, *nnode;
5400 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005401
paul1eb8ef22005-04-07 07:30:20 +00005402 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5403 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005404 if (peer->status == Established)
5405 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5406 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005407
paul545acaf2004-04-20 15:13:15 +00005408 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005409
paule210cf92005-06-15 19:15:35 +00005410 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005411 {
5412 work_queue_free (bm->process_main_queue);
5413 bm->process_main_queue = NULL;
5414 }
paule210cf92005-06-15 19:15:35 +00005415 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005416 {
5417 work_queue_free (bm->process_rsclient_queue);
5418 bm->process_rsclient_queue = NULL;
5419 }
paul545acaf2004-04-20 15:13:15 +00005420}