blob: 31ce5a164f5a7b8e8430da5428bea38f2136e14a [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
paul718e3742002-12-13 20:15:29 +00002066 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002067
2068 return 0;
2069}
2070
2071/* Delete BGP instance. */
2072int
2073bgp_delete (struct bgp *bgp)
2074{
2075 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002076 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002077 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002078 struct listnode *next;
2079 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002080 int i;
2081
2082 /* Delete static route. */
2083 bgp_static_delete (bgp);
2084
2085 /* Unset redistribution. */
2086 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2087 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2088 if (i != ZEBRA_ROUTE_BGP)
2089 bgp_redistribute_unset (bgp, afi, i);
2090
paul1eb8ef22005-04-07 07:30:20 +00002091 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2092 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002093
Chris Caputo228da422009-07-18 05:44:03 +00002094 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2095 peer_group_delete (group);
2096
2097 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002098
2099 if (bgp->peer_self) {
2100 peer_delete(bgp->peer_self);
2101 bgp->peer_self = NULL;
2102 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002103
2104 /* Remove visibility via the master list - there may however still be
2105 * routes to be processed still referencing the struct bgp.
2106 */
2107 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002108 if (list_isempty(bm->bgp))
2109 bgp_close ();
2110
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002111 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002112
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002113 return 0;
2114}
2115
2116static void bgp_free (struct bgp *);
2117
2118void
2119bgp_lock (struct bgp *bgp)
2120{
2121 ++bgp->lock;
2122}
2123
2124void
2125bgp_unlock(struct bgp *bgp)
2126{
Chris Caputo228da422009-07-18 05:44:03 +00002127 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002128 if (--bgp->lock == 0)
2129 bgp_free (bgp);
2130}
2131
2132static void
2133bgp_free (struct bgp *bgp)
2134{
2135 afi_t afi;
2136 safi_t safi;
2137
2138 list_delete (bgp->group);
2139 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002140 list_delete (bgp->rsclient);
2141
paul718e3742002-12-13 20:15:29 +00002142 if (bgp->name)
2143 free (bgp->name);
2144
2145 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2146 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2147 {
2148 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002149 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002150 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002151 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002152 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002153 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002154 }
2155 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002156}
2157
2158struct peer *
2159peer_lookup (struct bgp *bgp, union sockunion *su)
2160{
2161 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002163
Steve Hillfc4dc592009-07-28 17:54:35 +01002164 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002165 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002166 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2167 if (sockunion_same (&peer->su, su)
2168 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2169 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002170 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002171 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002172 {
2173 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002174
Paul Jakma2158ad22009-07-28 18:10:55 +01002175 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2176 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2177 if (sockunion_same (&peer->su, su)
2178 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2179 return peer;
paul718e3742002-12-13 20:15:29 +00002180 }
2181 return NULL;
2182}
2183
2184struct peer *
2185peer_lookup_with_open (union sockunion *su, as_t remote_as,
2186 struct in_addr *remote_id, int *as)
2187{
2188 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002189 struct listnode *node;
2190 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002191 struct bgp *bgp;
2192
Steve Hillfc4dc592009-07-28 17:54:35 +01002193 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002194 return NULL;
2195
Paul Jakma9d878772009-08-05 16:25:16 +01002196 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002197 {
Paul Jakma9d878772009-08-05 16:25:16 +01002198 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2199 {
2200 if (sockunion_same (&peer->su, su)
2201 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2202 {
2203 if (peer->as == remote_as
2204 && peer->remote_id.s_addr == remote_id->s_addr)
2205 return peer;
2206 if (peer->as == remote_as)
2207 *as = 1;
2208 }
2209 }
2210
2211 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2212 {
2213 if (sockunion_same (&peer->su, su)
2214 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2215 {
2216 if (peer->as == remote_as
2217 && peer->remote_id.s_addr == 0)
2218 return peer;
2219 if (peer->as == remote_as)
2220 *as = 1;
2221 }
2222 }
paul718e3742002-12-13 20:15:29 +00002223 }
2224 return NULL;
2225}
2226
2227/* If peer is configured at least one address family return 1. */
2228int
2229peer_active (struct peer *peer)
2230{
2231 if (peer->afc[AFI_IP][SAFI_UNICAST]
2232 || peer->afc[AFI_IP][SAFI_MULTICAST]
2233 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2234 || peer->afc[AFI_IP6][SAFI_UNICAST]
2235 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2236 return 1;
2237 return 0;
2238}
2239
2240/* If peer is negotiated at least one address family return 1. */
2241int
2242peer_active_nego (struct peer *peer)
2243{
2244 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2245 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2246 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2247 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2248 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2249 return 1;
2250 return 0;
2251}
2252
2253/* peer_flag_change_type. */
2254enum peer_change_type
2255{
2256 peer_change_none,
2257 peer_change_reset,
2258 peer_change_reset_in,
2259 peer_change_reset_out,
2260};
2261
paul94f2b392005-06-28 12:44:16 +00002262static void
paul718e3742002-12-13 20:15:29 +00002263peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2264 enum peer_change_type type)
2265{
2266 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2267 return;
2268
2269 if (type == peer_change_reset)
2270 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2271 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2272 else if (type == peer_change_reset_in)
2273 {
2274 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2275 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2276 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2277 else
2278 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2279 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2280 }
2281 else if (type == peer_change_reset_out)
2282 bgp_announce_route (peer, afi, safi);
2283}
2284
2285struct peer_flag_action
2286{
2287 /* Peer's flag. */
2288 u_int32_t flag;
2289
2290 /* This flag can be set for peer-group member. */
2291 u_char not_for_member;
2292
2293 /* Action when the flag is changed. */
2294 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002295
2296 /* Peer down cause */
2297 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002298};
2299
Stephen Hemminger03621952009-07-21 16:27:20 -07002300static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002301 {
2302 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2303 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2304 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2305 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2306 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002307 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002308 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002309 { 0, 0, 0 }
2310 };
2311
Stephen Hemminger03621952009-07-21 16:27:20 -07002312static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002313 {
2314 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2315 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2316 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2317 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2318 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2319 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2320 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2321 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2322 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2323 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2324 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2325 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2326 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002327 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002328 { 0, 0, 0 }
2329 };
2330
2331/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002332static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002333peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002334 struct peer_flag_action *action, u_int32_t flag)
2335{
2336 int i;
2337 int found = 0;
2338 int reset_in = 0;
2339 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002340 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002341
2342 /* Check peer's frag action. */
2343 for (i = 0; i < size; i++)
2344 {
2345 match = &action_list[i];
2346
2347 if (match->flag == 0)
2348 break;
2349
2350 if (match->flag & flag)
2351 {
2352 found = 1;
2353
2354 if (match->type == peer_change_reset_in)
2355 reset_in = 1;
2356 if (match->type == peer_change_reset_out)
2357 reset_out = 1;
2358 if (match->type == peer_change_reset)
2359 {
2360 reset_in = 1;
2361 reset_out = 1;
2362 }
2363 if (match->not_for_member)
2364 action->not_for_member = 1;
2365 }
2366 }
2367
2368 /* Set peer clear type. */
2369 if (reset_in && reset_out)
2370 action->type = peer_change_reset;
2371 else if (reset_in)
2372 action->type = peer_change_reset_in;
2373 else if (reset_out)
2374 action->type = peer_change_reset_out;
2375 else
2376 action->type = peer_change_none;
2377
2378 return found;
2379}
2380
paul94f2b392005-06-28 12:44:16 +00002381static void
paul718e3742002-12-13 20:15:29 +00002382peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2383{
2384 if (flag == PEER_FLAG_SHUTDOWN)
2385 {
2386 if (CHECK_FLAG (peer->flags, flag))
2387 {
hasso93406d82005-02-02 14:40:33 +00002388 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2389 peer_nsf_stop (peer);
2390
hasso0a486e52005-02-01 20:57:17 +00002391 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2392 if (peer->t_pmax_restart)
2393 {
2394 BGP_TIMER_OFF (peer->t_pmax_restart);
2395 if (BGP_DEBUG (events, EVENTS))
2396 zlog_debug ("%s Maximum-prefix restart timer canceled",
2397 peer->host);
2398 }
2399
hasso93406d82005-02-02 14:40:33 +00002400 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2401 peer_nsf_stop (peer);
2402
paul718e3742002-12-13 20:15:29 +00002403 if (peer->status == Established)
2404 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2405 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2406 else
2407 BGP_EVENT_ADD (peer, BGP_Stop);
2408 }
2409 else
2410 {
2411 peer->v_start = BGP_INIT_START_TIMER;
2412 BGP_EVENT_ADD (peer, BGP_Stop);
2413 }
2414 }
2415 else if (peer->status == Established)
2416 {
hassoc9502432005-02-01 22:01:48 +00002417 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2418 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2419 else if (flag == PEER_FLAG_PASSIVE)
2420 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002421 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002422 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002423
hassoc9502432005-02-01 22:01:48 +00002424 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2425 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002426 }
2427 else
2428 BGP_EVENT_ADD (peer, BGP_Stop);
2429}
2430
2431/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002432static int
paul718e3742002-12-13 20:15:29 +00002433peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2434{
2435 int found;
2436 int size;
2437 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002438 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002439 struct peer_flag_action action;
2440
2441 memset (&action, 0, sizeof (struct peer_flag_action));
2442 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2443
2444 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2445
2446 /* No flag action is found. */
2447 if (! found)
2448 return BGP_ERR_INVALID_FLAG;
2449
2450 /* Not for peer-group member. */
2451 if (action.not_for_member && peer_group_active (peer))
2452 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2453
2454 /* When unset the peer-group member's flag we have to check
2455 peer-group configuration. */
2456 if (! set && peer_group_active (peer))
2457 if (CHECK_FLAG (peer->group->conf->flags, flag))
2458 {
2459 if (flag == PEER_FLAG_SHUTDOWN)
2460 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2461 else
2462 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2463 }
2464
2465 /* Flag conflict check. */
2466 if (set
2467 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2468 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2469 return BGP_ERR_PEER_FLAG_CONFLICT;
2470
2471 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2472 {
2473 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2474 return 0;
2475 if (! set && ! CHECK_FLAG (peer->flags, flag))
2476 return 0;
2477 }
2478
2479 if (set)
2480 SET_FLAG (peer->flags, flag);
2481 else
2482 UNSET_FLAG (peer->flags, flag);
2483
2484 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2485 {
2486 if (action.type == peer_change_reset)
2487 peer_flag_modify_action (peer, flag);
2488
2489 return 0;
2490 }
2491
2492 /* peer-group member updates. */
2493 group = peer->group;
2494
paul1eb8ef22005-04-07 07:30:20 +00002495 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002496 {
2497 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2498 continue;
2499
2500 if (! set && ! CHECK_FLAG (peer->flags, flag))
2501 continue;
2502
2503 if (set)
2504 SET_FLAG (peer->flags, flag);
2505 else
2506 UNSET_FLAG (peer->flags, flag);
2507
2508 if (action.type == peer_change_reset)
2509 peer_flag_modify_action (peer, flag);
2510 }
2511 return 0;
2512}
2513
2514int
2515peer_flag_set (struct peer *peer, u_int32_t flag)
2516{
2517 return peer_flag_modify (peer, flag, 1);
2518}
2519
2520int
2521peer_flag_unset (struct peer *peer, u_int32_t flag)
2522{
2523 return peer_flag_modify (peer, flag, 0);
2524}
2525
paul94f2b392005-06-28 12:44:16 +00002526static int
paul718e3742002-12-13 20:15:29 +00002527peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2528{
2529 if (peer->af_group[afi][safi])
2530 return 1;
2531 return 0;
2532}
2533
paul94f2b392005-06-28 12:44:16 +00002534static int
paul718e3742002-12-13 20:15:29 +00002535peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2536 int set)
2537{
2538 int found;
2539 int size;
paul1eb8ef22005-04-07 07:30:20 +00002540 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002541 struct peer_group *group;
2542 struct peer_flag_action action;
2543
2544 memset (&action, 0, sizeof (struct peer_flag_action));
2545 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2546
2547 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2548
2549 /* No flag action is found. */
2550 if (! found)
2551 return BGP_ERR_INVALID_FLAG;
2552
2553 /* Adress family must be activated. */
2554 if (! peer->afc[afi][safi])
2555 return BGP_ERR_PEER_INACTIVE;
2556
2557 /* Not for peer-group member. */
2558 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2559 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2560
2561 /* Spcecial check for reflector client. */
2562 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2563 && peer_sort (peer) != BGP_PEER_IBGP)
2564 return BGP_ERR_NOT_INTERNAL_PEER;
2565
2566 /* Spcecial check for remove-private-AS. */
2567 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2568 && peer_sort (peer) == BGP_PEER_IBGP)
2569 return BGP_ERR_REMOVE_PRIVATE_AS;
2570
2571 /* When unset the peer-group member's flag we have to check
2572 peer-group configuration. */
2573 if (! set && peer->af_group[afi][safi])
2574 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2575 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2576
2577 /* When current flag configuration is same as requested one. */
2578 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2579 {
2580 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2581 return 0;
2582 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2583 return 0;
2584 }
2585
2586 if (set)
2587 SET_FLAG (peer->af_flags[afi][safi], flag);
2588 else
2589 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2590
2591 /* Execute action when peer is established. */
2592 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2593 && peer->status == Established)
2594 {
2595 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2596 bgp_clear_adj_in (peer, afi, safi);
2597 else
hassoe0701b72004-05-20 09:19:34 +00002598 {
2599 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2600 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2601 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2602 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2603 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2604 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2605 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2606 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2607
2608 peer_change_action (peer, afi, safi, action.type);
2609 }
2610
paul718e3742002-12-13 20:15:29 +00002611 }
2612
2613 /* Peer group member updates. */
2614 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2615 {
2616 group = peer->group;
2617
paul1eb8ef22005-04-07 07:30:20 +00002618 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002619 {
2620 if (! peer->af_group[afi][safi])
2621 continue;
2622
2623 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2624 continue;
2625
2626 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2627 continue;
2628
2629 if (set)
2630 SET_FLAG (peer->af_flags[afi][safi], flag);
2631 else
2632 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2633
2634 if (peer->status == Established)
2635 {
2636 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2637 bgp_clear_adj_in (peer, afi, safi);
2638 else
hassoe0701b72004-05-20 09:19:34 +00002639 {
2640 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2641 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2642 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2643 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2644 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2645 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2646 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2647 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2648
2649 peer_change_action (peer, afi, safi, action.type);
2650 }
paul718e3742002-12-13 20:15:29 +00002651 }
2652 }
2653 }
2654 return 0;
2655}
2656
2657int
2658peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2659{
2660 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2661}
2662
2663int
2664peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2665{
2666 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2667}
2668
2669/* EBGP multihop configuration. */
2670int
2671peer_ebgp_multihop_set (struct peer *peer, int ttl)
2672{
2673 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002674 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002675 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002676
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002677 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002678 return 0;
2679
Nick Hilliardfa411a22011-03-23 15:33:17 +00002680 /* see comment in peer_ttl_security_hops_set() */
2681 if (ttl != MAXTTL)
2682 {
2683 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2684 {
2685 group = peer->group;
2686 if (group->conf->gtsm_hops != 0)
2687 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2688
2689 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2690 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002691 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002692 continue;
2693
2694 if (peer1->gtsm_hops != 0)
2695 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2696 }
2697 }
2698 else
2699 {
2700 if (peer->gtsm_hops != 0)
2701 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2702 }
2703 }
2704
paul718e3742002-12-13 20:15:29 +00002705 peer->ttl = ttl;
2706
2707 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2708 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002709 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002710 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002711 }
2712 else
2713 {
2714 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002715 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002716 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002717 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002718 continue;
paul718e3742002-12-13 20:15:29 +00002719
pauleb821182004-05-01 08:44:08 +00002720 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002721
pauleb821182004-05-01 08:44:08 +00002722 if (peer->fd >= 0)
2723 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2724 }
paul718e3742002-12-13 20:15:29 +00002725 }
2726 return 0;
2727}
2728
2729int
2730peer_ebgp_multihop_unset (struct peer *peer)
2731{
2732 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002733 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002734
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002735 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002736 return 0;
2737
Nick Hilliardfa411a22011-03-23 15:33:17 +00002738 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2739 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2740
paul718e3742002-12-13 20:15:29 +00002741 if (peer_group_active (peer))
2742 peer->ttl = peer->group->conf->ttl;
2743 else
2744 peer->ttl = 1;
2745
2746 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2747 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002748 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002749 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002750 }
2751 else
2752 {
2753 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002754 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002755 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002756 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002757 continue;
paul718e3742002-12-13 20:15:29 +00002758
pauleb821182004-05-01 08:44:08 +00002759 peer->ttl = 1;
2760
2761 if (peer->fd >= 0)
2762 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2763 }
paul718e3742002-12-13 20:15:29 +00002764 }
2765 return 0;
2766}
2767
2768/* Neighbor description. */
2769int
2770peer_description_set (struct peer *peer, char *desc)
2771{
2772 if (peer->desc)
2773 XFREE (MTYPE_PEER_DESC, peer->desc);
2774
2775 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2776
2777 return 0;
2778}
2779
2780int
2781peer_description_unset (struct peer *peer)
2782{
2783 if (peer->desc)
2784 XFREE (MTYPE_PEER_DESC, peer->desc);
2785
2786 peer->desc = NULL;
2787
2788 return 0;
2789}
2790
2791/* Neighbor update-source. */
2792int
paulfd79ac92004-10-13 05:06:08 +00002793peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002794{
2795 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002796 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002797
2798 if (peer->update_if)
2799 {
2800 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2801 && strcmp (peer->update_if, ifname) == 0)
2802 return 0;
2803
2804 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2805 peer->update_if = NULL;
2806 }
2807
2808 if (peer->update_source)
2809 {
2810 sockunion_free (peer->update_source);
2811 peer->update_source = NULL;
2812 }
2813
2814 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2815
2816 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2817 {
2818 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002819 {
2820 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2821 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2822 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2823 }
paul718e3742002-12-13 20:15:29 +00002824 else
2825 BGP_EVENT_ADD (peer, BGP_Stop);
2826 return 0;
2827 }
2828
2829 /* peer-group member updates. */
2830 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002831 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002832 {
2833 if (peer->update_if)
2834 {
2835 if (strcmp (peer->update_if, ifname) == 0)
2836 continue;
2837
2838 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2839 peer->update_if = NULL;
2840 }
2841
2842 if (peer->update_source)
2843 {
2844 sockunion_free (peer->update_source);
2845 peer->update_source = NULL;
2846 }
2847
2848 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2849
2850 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002851 {
2852 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2853 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2854 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2855 }
paul718e3742002-12-13 20:15:29 +00002856 else
2857 BGP_EVENT_ADD (peer, BGP_Stop);
2858 }
2859 return 0;
2860}
2861
2862int
2863peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2864{
2865 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002866 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002867
2868 if (peer->update_source)
2869 {
2870 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2871 && sockunion_cmp (peer->update_source, su) == 0)
2872 return 0;
2873 sockunion_free (peer->update_source);
2874 peer->update_source = NULL;
2875 }
2876
2877 if (peer->update_if)
2878 {
2879 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2880 peer->update_if = NULL;
2881 }
2882
2883 peer->update_source = sockunion_dup (su);
2884
2885 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2886 {
2887 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002888 {
2889 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2890 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2891 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2892 }
paul718e3742002-12-13 20:15:29 +00002893 else
2894 BGP_EVENT_ADD (peer, BGP_Stop);
2895 return 0;
2896 }
2897
2898 /* peer-group member updates. */
2899 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002900 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002901 {
2902 if (peer->update_source)
2903 {
2904 if (sockunion_cmp (peer->update_source, su) == 0)
2905 continue;
2906 sockunion_free (peer->update_source);
2907 peer->update_source = NULL;
2908 }
2909
2910 if (peer->update_if)
2911 {
2912 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2913 peer->update_if = NULL;
2914 }
2915
2916 peer->update_source = sockunion_dup (su);
2917
2918 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002919 {
2920 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2923 }
paul718e3742002-12-13 20:15:29 +00002924 else
2925 BGP_EVENT_ADD (peer, BGP_Stop);
2926 }
2927 return 0;
2928}
2929
2930int
2931peer_update_source_unset (struct peer *peer)
2932{
2933 union sockunion *su;
2934 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002935 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002936
2937 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2938 && ! peer->update_source
2939 && ! peer->update_if)
2940 return 0;
2941
2942 if (peer->update_source)
2943 {
2944 sockunion_free (peer->update_source);
2945 peer->update_source = NULL;
2946 }
2947 if (peer->update_if)
2948 {
2949 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2950 peer->update_if = NULL;
2951 }
2952
2953 if (peer_group_active (peer))
2954 {
2955 group = peer->group;
2956
2957 if (group->conf->update_source)
2958 {
2959 su = sockunion_dup (group->conf->update_source);
2960 peer->update_source = su;
2961 }
2962 else if (group->conf->update_if)
2963 peer->update_if =
2964 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2965 }
2966
2967 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2968 {
2969 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002970 {
2971 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2972 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2973 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2974 }
paul718e3742002-12-13 20:15:29 +00002975 else
2976 BGP_EVENT_ADD (peer, BGP_Stop);
2977 return 0;
2978 }
2979
2980 /* peer-group member updates. */
2981 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002982 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002983 {
2984 if (! peer->update_source && ! peer->update_if)
2985 continue;
2986
2987 if (peer->update_source)
2988 {
2989 sockunion_free (peer->update_source);
2990 peer->update_source = NULL;
2991 }
2992
2993 if (peer->update_if)
2994 {
2995 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2996 peer->update_if = NULL;
2997 }
2998
2999 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003000 {
3001 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3002 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3003 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3004 }
paul718e3742002-12-13 20:15:29 +00003005 else
3006 BGP_EVENT_ADD (peer, BGP_Stop);
3007 }
3008 return 0;
3009}
3010
3011int
3012peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003013 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003014{
3015 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003016 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003017
3018 /* Adress family must be activated. */
3019 if (! peer->afc[afi][safi])
3020 return BGP_ERR_PEER_INACTIVE;
3021
3022 /* Default originate can't be used for peer group memeber. */
3023 if (peer_is_group_member (peer, afi, safi))
3024 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3025
3026 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3027 || (rmap && ! peer->default_rmap[afi][safi].name)
3028 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3029 {
3030 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3031
3032 if (rmap)
3033 {
3034 if (peer->default_rmap[afi][safi].name)
3035 free (peer->default_rmap[afi][safi].name);
3036 peer->default_rmap[afi][safi].name = strdup (rmap);
3037 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3038 }
3039 }
3040
3041 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3042 {
3043 if (peer->status == Established && peer->afc_nego[afi][safi])
3044 bgp_default_originate (peer, afi, safi, 0);
3045 return 0;
3046 }
3047
3048 /* peer-group member updates. */
3049 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003050 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003051 {
3052 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3053
3054 if (rmap)
3055 {
3056 if (peer->default_rmap[afi][safi].name)
3057 free (peer->default_rmap[afi][safi].name);
3058 peer->default_rmap[afi][safi].name = strdup (rmap);
3059 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3060 }
3061
3062 if (peer->status == Established && peer->afc_nego[afi][safi])
3063 bgp_default_originate (peer, afi, safi, 0);
3064 }
3065 return 0;
3066}
3067
3068int
3069peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3070{
3071 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003072 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003073
3074 /* Adress family must be activated. */
3075 if (! peer->afc[afi][safi])
3076 return BGP_ERR_PEER_INACTIVE;
3077
3078 /* Default originate can't be used for peer group memeber. */
3079 if (peer_is_group_member (peer, afi, safi))
3080 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3081
3082 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3083 {
3084 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3085
3086 if (peer->default_rmap[afi][safi].name)
3087 free (peer->default_rmap[afi][safi].name);
3088 peer->default_rmap[afi][safi].name = NULL;
3089 peer->default_rmap[afi][safi].map = NULL;
3090 }
3091
3092 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3093 {
3094 if (peer->status == Established && peer->afc_nego[afi][safi])
3095 bgp_default_originate (peer, afi, safi, 1);
3096 return 0;
3097 }
3098
3099 /* peer-group member updates. */
3100 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003101 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003102 {
3103 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3104
3105 if (peer->default_rmap[afi][safi].name)
3106 free (peer->default_rmap[afi][safi].name);
3107 peer->default_rmap[afi][safi].name = NULL;
3108 peer->default_rmap[afi][safi].map = NULL;
3109
3110 if (peer->status == Established && peer->afc_nego[afi][safi])
3111 bgp_default_originate (peer, afi, safi, 1);
3112 }
3113 return 0;
3114}
3115
3116int
3117peer_port_set (struct peer *peer, u_int16_t port)
3118{
3119 peer->port = port;
3120 return 0;
3121}
3122
3123int
3124peer_port_unset (struct peer *peer)
3125{
3126 peer->port = BGP_PORT_DEFAULT;
3127 return 0;
3128}
3129
3130/* neighbor weight. */
3131int
3132peer_weight_set (struct peer *peer, u_int16_t weight)
3133{
3134 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003135 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003136
3137 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3138 peer->weight = weight;
3139
3140 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3141 return 0;
3142
3143 /* peer-group member updates. */
3144 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003145 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003146 {
3147 peer->weight = group->conf->weight;
3148 }
3149 return 0;
3150}
3151
3152int
3153peer_weight_unset (struct peer *peer)
3154{
3155 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003157
3158 /* Set default weight. */
3159 if (peer_group_active (peer))
3160 peer->weight = peer->group->conf->weight;
3161 else
3162 peer->weight = 0;
3163
3164 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3165
3166 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3167 return 0;
3168
3169 /* peer-group member updates. */
3170 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003171 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003172 {
3173 peer->weight = 0;
3174 }
3175 return 0;
3176}
3177
3178int
3179peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3180{
3181 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003182 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003183
3184 /* Not for peer group memeber. */
3185 if (peer_group_active (peer))
3186 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3187
3188 /* keepalive value check. */
3189 if (keepalive > 65535)
3190 return BGP_ERR_INVALID_VALUE;
3191
3192 /* Holdtime value check. */
3193 if (holdtime > 65535)
3194 return BGP_ERR_INVALID_VALUE;
3195
3196 /* Holdtime value must be either 0 or greater than 3. */
3197 if (holdtime < 3 && holdtime != 0)
3198 return BGP_ERR_INVALID_VALUE;
3199
3200 /* Set value to the configuration. */
3201 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3202 peer->holdtime = holdtime;
3203 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3204
3205 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3206 return 0;
3207
3208 /* peer-group member updates. */
3209 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003210 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003211 {
3212 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3213 peer->holdtime = group->conf->holdtime;
3214 peer->keepalive = group->conf->keepalive;
3215 }
3216 return 0;
3217}
3218
3219int
3220peer_timers_unset (struct peer *peer)
3221{
3222 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003223 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003224
3225 if (peer_group_active (peer))
3226 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3227
3228 /* Clear configuration. */
3229 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3230 peer->keepalive = 0;
3231 peer->holdtime = 0;
3232
3233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3234 return 0;
3235
3236 /* peer-group member updates. */
3237 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003238 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003239 {
3240 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3241 peer->holdtime = 0;
3242 peer->keepalive = 0;
3243 }
3244
3245 return 0;
3246}
3247
3248int
3249peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3250{
3251 if (peer_group_active (peer))
3252 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3253
3254 if (connect > 65535)
3255 return BGP_ERR_INVALID_VALUE;
3256
3257 /* Set value to the configuration. */
3258 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3259 peer->connect = connect;
3260
3261 /* Set value to timer setting. */
3262 peer->v_connect = connect;
3263
3264 return 0;
3265}
3266
3267int
3268peer_timers_connect_unset (struct peer *peer)
3269{
3270 if (peer_group_active (peer))
3271 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3272
3273 /* Clear configuration. */
3274 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3275 peer->connect = 0;
3276
3277 /* Set timer setting to default value. */
3278 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3279
3280 return 0;
3281}
3282
3283int
3284peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3285{
3286 if (peer_group_active (peer))
3287 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3288
3289 if (routeadv > 600)
3290 return BGP_ERR_INVALID_VALUE;
3291
3292 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3293 peer->routeadv = routeadv;
3294 peer->v_routeadv = routeadv;
3295
3296 return 0;
3297}
3298
3299int
3300peer_advertise_interval_unset (struct peer *peer)
3301{
3302 if (peer_group_active (peer))
3303 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3304
3305 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3306 peer->routeadv = 0;
3307
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003308 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003309 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3310 else
3311 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3312
3313 return 0;
3314}
3315
paul718e3742002-12-13 20:15:29 +00003316/* neighbor interface */
3317int
paulfd79ac92004-10-13 05:06:08 +00003318peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003319{
3320 if (peer->ifname)
3321 free (peer->ifname);
3322 peer->ifname = strdup (str);
3323
3324 return 0;
3325}
3326
3327int
3328peer_interface_unset (struct peer *peer)
3329{
3330 if (peer->ifname)
3331 free (peer->ifname);
3332 peer->ifname = NULL;
3333
3334 return 0;
3335}
3336
3337/* Allow-as in. */
3338int
3339peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3340{
3341 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003342 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003343
3344 if (allow_num < 1 || allow_num > 10)
3345 return BGP_ERR_INVALID_VALUE;
3346
3347 if (peer->allowas_in[afi][safi] != allow_num)
3348 {
3349 peer->allowas_in[afi][safi] = allow_num;
3350 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3351 peer_change_action (peer, afi, safi, peer_change_reset_in);
3352 }
3353
3354 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3355 return 0;
3356
3357 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003358 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003359 {
3360 if (peer->allowas_in[afi][safi] != allow_num)
3361 {
3362 peer->allowas_in[afi][safi] = allow_num;
3363 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3364 peer_change_action (peer, afi, safi, peer_change_reset_in);
3365 }
3366
3367 }
3368 return 0;
3369}
3370
3371int
3372peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3373{
3374 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003375 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003376
3377 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3378 {
3379 peer->allowas_in[afi][safi] = 0;
3380 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3381 }
3382
3383 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3384 return 0;
3385
3386 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003387 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003388 {
3389 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3390 {
3391 peer->allowas_in[afi][safi] = 0;
3392 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3393 }
3394 }
3395 return 0;
3396}
3397
3398int
3399peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3400{
3401 struct bgp *bgp = peer->bgp;
3402 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003403 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003404
3405 if (peer_sort (peer) != BGP_PEER_EBGP
3406 && peer_sort (peer) != BGP_PEER_INTERNAL)
3407 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3408
3409 if (bgp->as == as)
3410 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3411
3412 if (peer_group_active (peer))
3413 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3414
3415 if (peer->change_local_as == as &&
3416 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3417 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3418 return 0;
3419
3420 peer->change_local_as = as;
3421 if (no_prepend)
3422 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3423 else
3424 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3425
3426 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3427 {
3428 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003429 {
3430 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3431 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3432 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3433 }
paul718e3742002-12-13 20:15:29 +00003434 else
3435 BGP_EVENT_ADD (peer, BGP_Stop);
3436
3437 return 0;
3438 }
3439
3440 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003441 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003442 {
3443 peer->change_local_as = as;
3444 if (no_prepend)
3445 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3446 else
3447 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3448
3449 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003450 {
3451 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3452 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3453 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3454 }
paul718e3742002-12-13 20:15:29 +00003455 else
3456 BGP_EVENT_ADD (peer, BGP_Stop);
3457 }
3458
3459 return 0;
3460}
3461
3462int
3463peer_local_as_unset (struct peer *peer)
3464{
3465 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003466 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003467
3468 if (peer_group_active (peer))
3469 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3470
3471 if (! peer->change_local_as)
3472 return 0;
3473
3474 peer->change_local_as = 0;
3475 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3476
3477 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3478 {
3479 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003480 {
3481 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3482 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3483 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3484 }
paul718e3742002-12-13 20:15:29 +00003485 else
3486 BGP_EVENT_ADD (peer, BGP_Stop);
3487
3488 return 0;
3489 }
3490
3491 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003492 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003493 {
3494 peer->change_local_as = 0;
3495 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3496
3497 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003498 {
3499 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3500 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3501 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3502 }
paul718e3742002-12-13 20:15:29 +00003503 else
3504 BGP_EVENT_ADD (peer, BGP_Stop);
3505 }
3506 return 0;
3507}
3508
Paul Jakma0df7c912008-07-21 21:02:49 +00003509/* Set password for authenticating with the peer. */
3510int
3511peer_password_set (struct peer *peer, const char *password)
3512{
3513 struct listnode *nn, *nnode;
3514 int len = password ? strlen(password) : 0;
3515 int ret = BGP_SUCCESS;
3516
3517 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3518 return BGP_ERR_INVALID_VALUE;
3519
3520 if (peer->password && strcmp (peer->password, password) == 0
3521 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3522 return 0;
3523
3524 if (peer->password)
3525 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3526
3527 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3528
3529 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3530 {
3531 if (peer->status == Established)
3532 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3533 else
3534 BGP_EVENT_ADD (peer, BGP_Stop);
3535
3536 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3537 }
3538
3539 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3540 {
3541 if (peer->password && strcmp (peer->password, password) == 0)
3542 continue;
3543
3544 if (peer->password)
3545 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3546
3547 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3548
3549 if (peer->status == Established)
3550 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3551 else
3552 BGP_EVENT_ADD (peer, BGP_Stop);
3553
3554 if (bgp_md5_set (peer) < 0)
3555 ret = BGP_ERR_TCPSIG_FAILED;
3556 }
3557
3558 return ret;
3559}
3560
3561int
3562peer_password_unset (struct peer *peer)
3563{
3564 struct listnode *nn, *nnode;
3565
3566 if (!peer->password
3567 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3568 return 0;
3569
3570 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3571 {
3572 if (peer_group_active (peer)
3573 && peer->group->conf->password
3574 && strcmp (peer->group->conf->password, peer->password) == 0)
3575 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3576
3577 if (peer->status == Established)
3578 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3579 else
3580 BGP_EVENT_ADD (peer, BGP_Stop);
3581
3582 if (peer->password)
3583 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3584
3585 peer->password = NULL;
3586
3587 bgp_md5_set (peer);
3588
3589 return 0;
3590 }
3591
3592 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3593 peer->password = NULL;
3594
3595 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3596 {
3597 if (!peer->password)
3598 continue;
3599
3600 if (peer->status == Established)
3601 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3602 else
3603 BGP_EVENT_ADD (peer, BGP_Stop);
3604
3605 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3606 peer->password = NULL;
3607
3608 bgp_md5_set (peer);
3609 }
3610
3611 return 0;
3612}
3613
paul718e3742002-12-13 20:15:29 +00003614/* Set distribute list to the peer. */
3615int
3616peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003617 const char *name)
paul718e3742002-12-13 20:15:29 +00003618{
3619 struct bgp_filter *filter;
3620 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003621 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003622
3623 if (! peer->afc[afi][safi])
3624 return BGP_ERR_PEER_INACTIVE;
3625
3626 if (direct != FILTER_IN && direct != FILTER_OUT)
3627 return BGP_ERR_INVALID_VALUE;
3628
3629 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3630 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3631
3632 filter = &peer->filter[afi][safi];
3633
3634 if (filter->plist[direct].name)
3635 return BGP_ERR_PEER_FILTER_CONFLICT;
3636
3637 if (filter->dlist[direct].name)
3638 free (filter->dlist[direct].name);
3639 filter->dlist[direct].name = strdup (name);
3640 filter->dlist[direct].alist = access_list_lookup (afi, name);
3641
3642 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3643 return 0;
3644
3645 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003646 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003647 {
3648 filter = &peer->filter[afi][safi];
3649
3650 if (! peer->af_group[afi][safi])
3651 continue;
3652
3653 if (filter->dlist[direct].name)
3654 free (filter->dlist[direct].name);
3655 filter->dlist[direct].name = strdup (name);
3656 filter->dlist[direct].alist = access_list_lookup (afi, name);
3657 }
3658
3659 return 0;
3660}
3661
3662int
3663peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3664{
3665 struct bgp_filter *filter;
3666 struct bgp_filter *gfilter;
3667 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003668 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003669
3670 if (! peer->afc[afi][safi])
3671 return BGP_ERR_PEER_INACTIVE;
3672
3673 if (direct != FILTER_IN && direct != FILTER_OUT)
3674 return BGP_ERR_INVALID_VALUE;
3675
3676 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3677 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3678
3679 filter = &peer->filter[afi][safi];
3680
3681 /* apply peer-group filter */
3682 if (peer->af_group[afi][safi])
3683 {
3684 gfilter = &peer->group->conf->filter[afi][safi];
3685
3686 if (gfilter->dlist[direct].name)
3687 {
3688 if (filter->dlist[direct].name)
3689 free (filter->dlist[direct].name);
3690 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3691 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3692 return 0;
3693 }
3694 }
3695
3696 if (filter->dlist[direct].name)
3697 free (filter->dlist[direct].name);
3698 filter->dlist[direct].name = NULL;
3699 filter->dlist[direct].alist = NULL;
3700
3701 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3702 return 0;
3703
3704 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003705 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003706 {
3707 filter = &peer->filter[afi][safi];
3708
3709 if (! peer->af_group[afi][safi])
3710 continue;
3711
3712 if (filter->dlist[direct].name)
3713 free (filter->dlist[direct].name);
3714 filter->dlist[direct].name = NULL;
3715 filter->dlist[direct].alist = NULL;
3716 }
3717
3718 return 0;
3719}
3720
3721/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003722static void
paul718e3742002-12-13 20:15:29 +00003723peer_distribute_update (struct access_list *access)
3724{
3725 afi_t afi;
3726 safi_t safi;
3727 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003728 struct listnode *mnode, *mnnode;
3729 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003730 struct bgp *bgp;
3731 struct peer *peer;
3732 struct peer_group *group;
3733 struct bgp_filter *filter;
3734
paul1eb8ef22005-04-07 07:30:20 +00003735 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003736 {
paul1eb8ef22005-04-07 07:30:20 +00003737 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003738 {
3739 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3740 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3741 {
3742 filter = &peer->filter[afi][safi];
3743
3744 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3745 {
3746 if (filter->dlist[direct].name)
3747 filter->dlist[direct].alist =
3748 access_list_lookup (afi, filter->dlist[direct].name);
3749 else
3750 filter->dlist[direct].alist = NULL;
3751 }
3752 }
3753 }
paul1eb8ef22005-04-07 07:30:20 +00003754 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003755 {
3756 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3757 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3758 {
3759 filter = &group->conf->filter[afi][safi];
3760
3761 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3762 {
3763 if (filter->dlist[direct].name)
3764 filter->dlist[direct].alist =
3765 access_list_lookup (afi, filter->dlist[direct].name);
3766 else
3767 filter->dlist[direct].alist = NULL;
3768 }
3769 }
3770 }
3771 }
3772}
3773
3774/* Set prefix list to the peer. */
3775int
3776peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003777 const char *name)
paul718e3742002-12-13 20:15:29 +00003778{
3779 struct bgp_filter *filter;
3780 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003781 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003782
3783 if (! peer->afc[afi][safi])
3784 return BGP_ERR_PEER_INACTIVE;
3785
3786 if (direct != FILTER_IN && direct != FILTER_OUT)
3787 return BGP_ERR_INVALID_VALUE;
3788
3789 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3790 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3791
3792 filter = &peer->filter[afi][safi];
3793
3794 if (filter->dlist[direct].name)
3795 return BGP_ERR_PEER_FILTER_CONFLICT;
3796
3797 if (filter->plist[direct].name)
3798 free (filter->plist[direct].name);
3799 filter->plist[direct].name = strdup (name);
3800 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3801
3802 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3803 return 0;
3804
3805 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003806 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003807 {
3808 filter = &peer->filter[afi][safi];
3809
3810 if (! peer->af_group[afi][safi])
3811 continue;
3812
3813 if (filter->plist[direct].name)
3814 free (filter->plist[direct].name);
3815 filter->plist[direct].name = strdup (name);
3816 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3817 }
3818 return 0;
3819}
3820
3821int
3822peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3823{
3824 struct bgp_filter *filter;
3825 struct bgp_filter *gfilter;
3826 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003827 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003828
3829 if (! peer->afc[afi][safi])
3830 return BGP_ERR_PEER_INACTIVE;
3831
3832 if (direct != FILTER_IN && direct != FILTER_OUT)
3833 return BGP_ERR_INVALID_VALUE;
3834
3835 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3836 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3837
3838 filter = &peer->filter[afi][safi];
3839
3840 /* apply peer-group filter */
3841 if (peer->af_group[afi][safi])
3842 {
3843 gfilter = &peer->group->conf->filter[afi][safi];
3844
3845 if (gfilter->plist[direct].name)
3846 {
3847 if (filter->plist[direct].name)
3848 free (filter->plist[direct].name);
3849 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3850 filter->plist[direct].plist = gfilter->plist[direct].plist;
3851 return 0;
3852 }
3853 }
3854
3855 if (filter->plist[direct].name)
3856 free (filter->plist[direct].name);
3857 filter->plist[direct].name = NULL;
3858 filter->plist[direct].plist = NULL;
3859
3860 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3861 return 0;
3862
3863 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003864 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003865 {
3866 filter = &peer->filter[afi][safi];
3867
3868 if (! peer->af_group[afi][safi])
3869 continue;
3870
3871 if (filter->plist[direct].name)
3872 free (filter->plist[direct].name);
3873 filter->plist[direct].name = NULL;
3874 filter->plist[direct].plist = NULL;
3875 }
3876
3877 return 0;
3878}
3879
3880/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003881static void
paul718e3742002-12-13 20:15:29 +00003882peer_prefix_list_update (struct prefix_list *plist)
3883{
paul1eb8ef22005-04-07 07:30:20 +00003884 struct listnode *mnode, *mnnode;
3885 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003886 struct bgp *bgp;
3887 struct peer *peer;
3888 struct peer_group *group;
3889 struct bgp_filter *filter;
3890 afi_t afi;
3891 safi_t safi;
3892 int direct;
3893
paul1eb8ef22005-04-07 07:30:20 +00003894 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003895 {
paul1eb8ef22005-04-07 07:30:20 +00003896 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003897 {
3898 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3899 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3900 {
3901 filter = &peer->filter[afi][safi];
3902
3903 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3904 {
3905 if (filter->plist[direct].name)
3906 filter->plist[direct].plist =
3907 prefix_list_lookup (afi, filter->plist[direct].name);
3908 else
3909 filter->plist[direct].plist = NULL;
3910 }
3911 }
3912 }
paul1eb8ef22005-04-07 07:30:20 +00003913 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003914 {
3915 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3916 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3917 {
3918 filter = &group->conf->filter[afi][safi];
3919
3920 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3921 {
3922 if (filter->plist[direct].name)
3923 filter->plist[direct].plist =
3924 prefix_list_lookup (afi, filter->plist[direct].name);
3925 else
3926 filter->plist[direct].plist = NULL;
3927 }
3928 }
3929 }
3930 }
3931}
3932
3933int
3934peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003935 const char *name)
paul718e3742002-12-13 20:15:29 +00003936{
3937 struct bgp_filter *filter;
3938 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003939 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003940
3941 if (! peer->afc[afi][safi])
3942 return BGP_ERR_PEER_INACTIVE;
3943
3944 if (direct != FILTER_IN && direct != FILTER_OUT)
3945 return BGP_ERR_INVALID_VALUE;
3946
3947 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3948 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3949
3950 filter = &peer->filter[afi][safi];
3951
3952 if (filter->aslist[direct].name)
3953 free (filter->aslist[direct].name);
3954 filter->aslist[direct].name = strdup (name);
3955 filter->aslist[direct].aslist = as_list_lookup (name);
3956
3957 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3958 return 0;
3959
3960 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003961 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003962 {
3963 filter = &peer->filter[afi][safi];
3964
3965 if (! peer->af_group[afi][safi])
3966 continue;
3967
3968 if (filter->aslist[direct].name)
3969 free (filter->aslist[direct].name);
3970 filter->aslist[direct].name = strdup (name);
3971 filter->aslist[direct].aslist = as_list_lookup (name);
3972 }
3973 return 0;
3974}
3975
3976int
3977peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3978{
3979 struct bgp_filter *filter;
3980 struct bgp_filter *gfilter;
3981 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003982 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003983
3984 if (! peer->afc[afi][safi])
3985 return BGP_ERR_PEER_INACTIVE;
3986
hassob5f29602005-05-25 21:00:28 +00003987 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003988 return BGP_ERR_INVALID_VALUE;
3989
hassob5f29602005-05-25 21:00:28 +00003990 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003991 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3992
3993 filter = &peer->filter[afi][safi];
3994
3995 /* apply peer-group filter */
3996 if (peer->af_group[afi][safi])
3997 {
3998 gfilter = &peer->group->conf->filter[afi][safi];
3999
4000 if (gfilter->aslist[direct].name)
4001 {
4002 if (filter->aslist[direct].name)
4003 free (filter->aslist[direct].name);
4004 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4005 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4006 return 0;
4007 }
4008 }
4009
4010 if (filter->aslist[direct].name)
4011 free (filter->aslist[direct].name);
4012 filter->aslist[direct].name = NULL;
4013 filter->aslist[direct].aslist = NULL;
4014
4015 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4016 return 0;
4017
4018 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004019 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004020 {
4021 filter = &peer->filter[afi][safi];
4022
4023 if (! peer->af_group[afi][safi])
4024 continue;
4025
4026 if (filter->aslist[direct].name)
4027 free (filter->aslist[direct].name);
4028 filter->aslist[direct].name = NULL;
4029 filter->aslist[direct].aslist = NULL;
4030 }
4031
4032 return 0;
4033}
4034
paul94f2b392005-06-28 12:44:16 +00004035static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004036peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004037{
4038 afi_t afi;
4039 safi_t safi;
4040 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004041 struct listnode *mnode, *mnnode;
4042 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004043 struct bgp *bgp;
4044 struct peer *peer;
4045 struct peer_group *group;
4046 struct bgp_filter *filter;
4047
paul1eb8ef22005-04-07 07:30:20 +00004048 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004049 {
paul1eb8ef22005-04-07 07:30:20 +00004050 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004051 {
4052 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4053 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4054 {
4055 filter = &peer->filter[afi][safi];
4056
4057 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4058 {
4059 if (filter->aslist[direct].name)
4060 filter->aslist[direct].aslist =
4061 as_list_lookup (filter->aslist[direct].name);
4062 else
4063 filter->aslist[direct].aslist = NULL;
4064 }
4065 }
4066 }
paul1eb8ef22005-04-07 07:30:20 +00004067 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004068 {
4069 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4070 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4071 {
4072 filter = &group->conf->filter[afi][safi];
4073
4074 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4075 {
4076 if (filter->aslist[direct].name)
4077 filter->aslist[direct].aslist =
4078 as_list_lookup (filter->aslist[direct].name);
4079 else
4080 filter->aslist[direct].aslist = NULL;
4081 }
4082 }
4083 }
4084 }
4085}
4086
4087/* Set route-map to the peer. */
4088int
4089peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004090 const char *name)
paul718e3742002-12-13 20:15:29 +00004091{
4092 struct bgp_filter *filter;
4093 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004094 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004095
4096 if (! peer->afc[afi][safi])
4097 return BGP_ERR_PEER_INACTIVE;
4098
paulfee0f4c2004-09-13 05:12:46 +00004099 if (direct != RMAP_IN && direct != RMAP_OUT &&
4100 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004101 return BGP_ERR_INVALID_VALUE;
4102
paulfee0f4c2004-09-13 05:12:46 +00004103 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4104 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004105 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4106
4107 filter = &peer->filter[afi][safi];
4108
4109 if (filter->map[direct].name)
4110 free (filter->map[direct].name);
4111
4112 filter->map[direct].name = strdup (name);
4113 filter->map[direct].map = route_map_lookup_by_name (name);
4114
4115 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4116 return 0;
4117
4118 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004119 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004120 {
4121 filter = &peer->filter[afi][safi];
4122
4123 if (! peer->af_group[afi][safi])
4124 continue;
4125
4126 if (filter->map[direct].name)
4127 free (filter->map[direct].name);
4128 filter->map[direct].name = strdup (name);
4129 filter->map[direct].map = route_map_lookup_by_name (name);
4130 }
4131 return 0;
4132}
4133
4134/* Unset route-map from the peer. */
4135int
4136peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4137{
4138 struct bgp_filter *filter;
4139 struct bgp_filter *gfilter;
4140 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004141 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004142
4143 if (! peer->afc[afi][safi])
4144 return BGP_ERR_PEER_INACTIVE;
4145
hassob5f29602005-05-25 21:00:28 +00004146 if (direct != RMAP_IN && direct != RMAP_OUT &&
4147 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004148 return BGP_ERR_INVALID_VALUE;
4149
hassob5f29602005-05-25 21:00:28 +00004150 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4151 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004152 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4153
4154 filter = &peer->filter[afi][safi];
4155
4156 /* apply peer-group filter */
4157 if (peer->af_group[afi][safi])
4158 {
4159 gfilter = &peer->group->conf->filter[afi][safi];
4160
4161 if (gfilter->map[direct].name)
4162 {
4163 if (filter->map[direct].name)
4164 free (filter->map[direct].name);
4165 filter->map[direct].name = strdup (gfilter->map[direct].name);
4166 filter->map[direct].map = gfilter->map[direct].map;
4167 return 0;
4168 }
4169 }
4170
4171 if (filter->map[direct].name)
4172 free (filter->map[direct].name);
4173 filter->map[direct].name = NULL;
4174 filter->map[direct].map = NULL;
4175
4176 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4177 return 0;
4178
4179 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004180 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004181 {
4182 filter = &peer->filter[afi][safi];
4183
4184 if (! peer->af_group[afi][safi])
4185 continue;
4186
4187 if (filter->map[direct].name)
4188 free (filter->map[direct].name);
4189 filter->map[direct].name = NULL;
4190 filter->map[direct].map = NULL;
4191 }
4192 return 0;
4193}
4194
4195/* Set unsuppress-map to the peer. */
4196int
paulfd79ac92004-10-13 05:06:08 +00004197peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4198 const char *name)
paul718e3742002-12-13 20:15:29 +00004199{
4200 struct bgp_filter *filter;
4201 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004202 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004203
4204 if (! peer->afc[afi][safi])
4205 return BGP_ERR_PEER_INACTIVE;
4206
4207 if (peer_is_group_member (peer, afi, safi))
4208 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4209
4210 filter = &peer->filter[afi][safi];
4211
4212 if (filter->usmap.name)
4213 free (filter->usmap.name);
4214
4215 filter->usmap.name = strdup (name);
4216 filter->usmap.map = route_map_lookup_by_name (name);
4217
4218 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4219 return 0;
4220
4221 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004222 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004223 {
4224 filter = &peer->filter[afi][safi];
4225
4226 if (! peer->af_group[afi][safi])
4227 continue;
4228
4229 if (filter->usmap.name)
4230 free (filter->usmap.name);
4231 filter->usmap.name = strdup (name);
4232 filter->usmap.map = route_map_lookup_by_name (name);
4233 }
4234 return 0;
4235}
4236
4237/* Unset route-map from the peer. */
4238int
4239peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4240{
4241 struct bgp_filter *filter;
4242 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004243 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004244
4245 if (! peer->afc[afi][safi])
4246 return BGP_ERR_PEER_INACTIVE;
4247
4248 if (peer_is_group_member (peer, afi, safi))
4249 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4250
4251 filter = &peer->filter[afi][safi];
4252
4253 if (filter->usmap.name)
4254 free (filter->usmap.name);
4255 filter->usmap.name = NULL;
4256 filter->usmap.map = NULL;
4257
4258 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4259 return 0;
4260
4261 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004262 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004263 {
4264 filter = &peer->filter[afi][safi];
4265
4266 if (! peer->af_group[afi][safi])
4267 continue;
4268
4269 if (filter->usmap.name)
4270 free (filter->usmap.name);
4271 filter->usmap.name = NULL;
4272 filter->usmap.map = NULL;
4273 }
4274 return 0;
4275}
4276
4277int
4278peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004279 u_int32_t max, u_char threshold,
4280 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004281{
4282 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004283 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004284
4285 if (! peer->afc[afi][safi])
4286 return BGP_ERR_PEER_INACTIVE;
4287
4288 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4289 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004290 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004291 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004292 if (warning)
4293 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4294 else
4295 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4296
4297 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4298 return 0;
4299
4300 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004301 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004302 {
4303 if (! peer->af_group[afi][safi])
4304 continue;
4305
4306 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4307 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004308 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004309 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004310 if (warning)
4311 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4312 else
4313 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4314 }
4315 return 0;
4316}
4317
4318int
4319peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4320{
4321 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004322 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004323
4324 if (! peer->afc[afi][safi])
4325 return BGP_ERR_PEER_INACTIVE;
4326
4327 /* apply peer-group config */
4328 if (peer->af_group[afi][safi])
4329 {
4330 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4331 PEER_FLAG_MAX_PREFIX))
4332 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4333 else
4334 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4335
4336 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4337 PEER_FLAG_MAX_PREFIX_WARNING))
4338 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4339 else
4340 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4341
4342 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004343 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004344 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004345 return 0;
4346 }
4347
4348 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4349 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4350 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004351 peer->pmax_threshold[afi][safi] = 0;
4352 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004353
4354 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4355 return 0;
4356
4357 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004358 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004359 {
4360 if (! peer->af_group[afi][safi])
4361 continue;
4362
4363 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4364 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4365 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004366 peer->pmax_threshold[afi][safi] = 0;
4367 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004368 }
4369 return 0;
4370}
4371
Nick Hilliardfa411a22011-03-23 15:33:17 +00004372/* Set # of hops between us and BGP peer. */
4373int
4374peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4375{
4376 struct peer_group *group;
4377 struct listnode *node, *nnode;
4378 struct peer *peer1;
4379 int ret;
4380
4381 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4382
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004383 if (peer->sort == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004384 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004385
4386 /* We cannot configure ttl-security hops when ebgp-multihop is already
4387 set. For non peer-groups, the check is simple. For peer-groups, it's
4388 slightly messy, because we need to check both the peer-group structure
4389 and all peer-group members for any trace of ebgp-multihop configuration
4390 before actually applying the ttl-security rules. Cisco really made a
4391 mess of this configuration parameter, and OpenBGPD got it right.
4392 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004393
4394 if (peer->gtsm_hops == 0) {
4395 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4396 {
4397 group = peer->group;
4398 if (group->conf->ttl != 1)
4399 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004400
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004401 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4402 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004403 if (peer1->sort == BGP_PEER_IBGP)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004404 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004405
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004406 if (peer1->ttl != 1)
4407 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4408 }
4409 }
4410 else
4411 {
4412 if (peer->ttl != 1)
4413 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4414 }
4415 /* specify MAXTTL on outgoing packets */
4416 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4417 if (ret != 0)
4418 return ret;
4419 }
4420
Nick Hilliardfa411a22011-03-23 15:33:17 +00004421 peer->gtsm_hops = gtsm_hops;
4422
Nick Hilliardfa411a22011-03-23 15:33:17 +00004423 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4424 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004425 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004426 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4427 }
4428 else
4429 {
4430 group = peer->group;
4431 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4432 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004433 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004434 continue;
4435
4436 peer->gtsm_hops = group->conf->gtsm_hops;
4437
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004438 /* Change setting of existing peer
4439 * established then change value (may break connectivity)
4440 * not established yet (teardown session and restart)
4441 * no session then do nothing (will get handled by next connection)
4442 */
4443 if (peer->status == Established)
4444 {
4445 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4446 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4447 MAXTTL + 1 - peer->gtsm_hops);
4448 }
4449 else if (peer->status < Established)
4450 {
4451 if (BGP_DEBUG (events, EVENTS))
4452 zlog_debug ("%s Min-ttl changed", peer->host);
4453 BGP_EVENT_ADD (peer, BGP_Stop);
4454 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004455 }
4456 }
4457
4458 return 0;
4459}
4460
4461int
4462peer_ttl_security_hops_unset (struct peer *peer)
4463{
4464 struct peer_group *group;
4465 struct listnode *node, *nnode;
4466 struct peer *opeer;
4467
4468 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4469
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004470 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004471 return 0;
4472
4473 /* if a peer-group member, then reset to peer-group default rather than 0 */
4474 if (peer_group_active (peer))
4475 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4476 else
4477 peer->gtsm_hops = 0;
4478
4479 opeer = peer;
4480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4481 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004482 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004483 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4484 }
4485 else
4486 {
4487 group = peer->group;
4488 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4489 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004490 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004491 continue;
4492
4493 peer->gtsm_hops = 0;
4494
4495 if (peer->fd >= 0)
4496 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4497 }
4498 }
4499
4500 return peer_ebgp_multihop_unset (opeer);
4501}
4502
paul718e3742002-12-13 20:15:29 +00004503int
4504peer_clear (struct peer *peer)
4505{
4506 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4507 {
hasso0a486e52005-02-01 20:57:17 +00004508 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4509 {
4510 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4511 if (peer->t_pmax_restart)
4512 {
4513 BGP_TIMER_OFF (peer->t_pmax_restart);
4514 if (BGP_DEBUG (events, EVENTS))
4515 zlog_debug ("%s Maximum-prefix restart timer canceled",
4516 peer->host);
4517 }
4518 BGP_EVENT_ADD (peer, BGP_Start);
4519 return 0;
4520 }
4521
paul718e3742002-12-13 20:15:29 +00004522 peer->v_start = BGP_INIT_START_TIMER;
4523 if (peer->status == Established)
4524 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4525 BGP_NOTIFY_CEASE_ADMIN_RESET);
4526 else
4527 BGP_EVENT_ADD (peer, BGP_Stop);
4528 }
4529 return 0;
4530}
4531
4532int
4533peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4534 enum bgp_clear_type stype)
4535{
4536 if (peer->status != Established)
4537 return 0;
4538
4539 if (! peer->afc[afi][safi])
4540 return BGP_ERR_AF_UNCONFIGURED;
4541
paulfee0f4c2004-09-13 05:12:46 +00004542 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4543 {
4544 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4545 return 0;
4546 bgp_check_local_routes_rsclient (peer, afi, safi);
4547 bgp_soft_reconfig_rsclient (peer, afi, safi);
4548 }
4549
paul718e3742002-12-13 20:15:29 +00004550 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4551 bgp_announce_route (peer, afi, safi);
4552
4553 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4554 {
4555 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4556 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4557 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4558 {
4559 struct bgp_filter *filter = &peer->filter[afi][safi];
4560 u_char prefix_type;
4561
4562 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4563 prefix_type = ORF_TYPE_PREFIX;
4564 else
4565 prefix_type = ORF_TYPE_PREFIX_OLD;
4566
4567 if (filter->plist[FILTER_IN].plist)
4568 {
4569 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4570 bgp_route_refresh_send (peer, afi, safi,
4571 prefix_type, REFRESH_DEFER, 1);
4572 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4573 REFRESH_IMMEDIATE, 0);
4574 }
4575 else
4576 {
4577 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4578 bgp_route_refresh_send (peer, afi, safi,
4579 prefix_type, REFRESH_IMMEDIATE, 1);
4580 else
4581 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4582 }
4583 return 0;
4584 }
4585 }
4586
4587 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4588 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4589 {
4590 /* If neighbor has soft reconfiguration inbound flag.
4591 Use Adj-RIB-In database. */
4592 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4593 bgp_soft_reconfig_in (peer, afi, safi);
4594 else
4595 {
4596 /* If neighbor has route refresh capability, send route refresh
4597 message to the peer. */
4598 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4599 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4600 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4601 else
4602 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4603 }
4604 }
4605 return 0;
4606}
4607
paulfd79ac92004-10-13 05:06:08 +00004608/* Display peer uptime.*/
4609/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004610char *
4611peer_uptime (time_t uptime2, char *buf, size_t len)
4612{
4613 time_t uptime1;
4614 struct tm *tm;
4615
4616 /* Check buffer length. */
4617 if (len < BGP_UPTIME_LEN)
4618 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004619 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004620 /* XXX: should return status instead of buf... */
4621 snprintf (buf, len, "<error> ");
4622 return buf;
paul718e3742002-12-13 20:15:29 +00004623 }
4624
4625 /* If there is no connection has been done before print `never'. */
4626 if (uptime2 == 0)
4627 {
4628 snprintf (buf, len, "never ");
4629 return buf;
4630 }
4631
4632 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004633 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004634 uptime1 -= uptime2;
4635 tm = gmtime (&uptime1);
4636
4637 /* Making formatted timer strings. */
4638#define ONE_DAY_SECOND 60*60*24
4639#define ONE_WEEK_SECOND 60*60*24*7
4640
4641 if (uptime1 < ONE_DAY_SECOND)
4642 snprintf (buf, len, "%02d:%02d:%02d",
4643 tm->tm_hour, tm->tm_min, tm->tm_sec);
4644 else if (uptime1 < ONE_WEEK_SECOND)
4645 snprintf (buf, len, "%dd%02dh%02dm",
4646 tm->tm_yday, tm->tm_hour, tm->tm_min);
4647 else
4648 snprintf (buf, len, "%02dw%dd%02dh",
4649 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4650 return buf;
4651}
4652
paul94f2b392005-06-28 12:44:16 +00004653static void
paul718e3742002-12-13 20:15:29 +00004654bgp_config_write_filter (struct vty *vty, struct peer *peer,
4655 afi_t afi, safi_t safi)
4656{
4657 struct bgp_filter *filter;
4658 struct bgp_filter *gfilter = NULL;
4659 char *addr;
4660 int in = FILTER_IN;
4661 int out = FILTER_OUT;
4662
4663 addr = peer->host;
4664 filter = &peer->filter[afi][safi];
4665 if (peer->af_group[afi][safi])
4666 gfilter = &peer->group->conf->filter[afi][safi];
4667
4668 /* distribute-list. */
4669 if (filter->dlist[in].name)
4670 if (! gfilter || ! gfilter->dlist[in].name
4671 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4672 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4673 filter->dlist[in].name, VTY_NEWLINE);
4674 if (filter->dlist[out].name && ! gfilter)
4675 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4676 filter->dlist[out].name, VTY_NEWLINE);
4677
4678 /* prefix-list. */
4679 if (filter->plist[in].name)
4680 if (! gfilter || ! gfilter->plist[in].name
4681 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4682 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4683 filter->plist[in].name, VTY_NEWLINE);
4684 if (filter->plist[out].name && ! gfilter)
4685 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4686 filter->plist[out].name, VTY_NEWLINE);
4687
4688 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004689 if (filter->map[RMAP_IN].name)
4690 if (! gfilter || ! gfilter->map[RMAP_IN].name
4691 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004692 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004693 filter->map[RMAP_IN].name, VTY_NEWLINE);
4694 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004695 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004696 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4697 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4698 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4699 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4700 if (filter->map[RMAP_EXPORT].name)
4701 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4702 || strcmp (filter->map[RMAP_EXPORT].name,
4703 gfilter->map[RMAP_EXPORT].name) != 0)
4704 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4705 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004706
4707 /* unsuppress-map */
4708 if (filter->usmap.name && ! gfilter)
4709 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4710 filter->usmap.name, VTY_NEWLINE);
4711
4712 /* filter-list. */
4713 if (filter->aslist[in].name)
4714 if (! gfilter || ! gfilter->aslist[in].name
4715 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4716 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4717 filter->aslist[in].name, VTY_NEWLINE);
4718 if (filter->aslist[out].name && ! gfilter)
4719 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4720 filter->aslist[out].name, VTY_NEWLINE);
4721}
4722
4723/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004724static void
paul718e3742002-12-13 20:15:29 +00004725bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4726 struct peer *peer, afi_t afi, safi_t safi)
4727{
paul718e3742002-12-13 20:15:29 +00004728 struct peer *g_peer = NULL;
4729 char buf[SU_ADDRSTRLEN];
4730 char *addr;
4731
paul718e3742002-12-13 20:15:29 +00004732 addr = peer->host;
4733 if (peer_group_active (peer))
4734 g_peer = peer->group->conf;
4735
4736 /************************************
4737 ****** Global to the neighbor ******
4738 ************************************/
4739 if (afi == AFI_IP && safi == SAFI_UNICAST)
4740 {
4741 /* remote-as. */
4742 if (! peer_group_active (peer))
4743 {
4744 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4745 vty_out (vty, " neighbor %s peer-group%s", addr,
4746 VTY_NEWLINE);
4747 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004748 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004749 VTY_NEWLINE);
4750 }
4751 else
4752 {
4753 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004754 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004755 VTY_NEWLINE);
4756 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4757 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4758 peer->group->name, VTY_NEWLINE);
4759 }
4760
4761 /* local-as. */
4762 if (peer->change_local_as)
4763 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004764 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004765 peer->change_local_as,
4766 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4767 " no-prepend" : "", VTY_NEWLINE);
4768
4769 /* Description. */
4770 if (peer->desc)
4771 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4772 VTY_NEWLINE);
4773
4774 /* Shutdown. */
4775 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4776 if (! peer_group_active (peer) ||
4777 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4778 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4779
Paul Jakma0df7c912008-07-21 21:02:49 +00004780 /* Password. */
4781 if (peer->password)
4782 if (!peer_group_active (peer)
4783 || ! g_peer->password
4784 || strcmp (peer->password, g_peer->password) != 0)
4785 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4786 VTY_NEWLINE);
4787
paul718e3742002-12-13 20:15:29 +00004788 /* BGP port. */
4789 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004790 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004791 VTY_NEWLINE);
4792
4793 /* Local interface name. */
4794 if (peer->ifname)
4795 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4796 VTY_NEWLINE);
4797
4798 /* Passive. */
4799 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4800 if (! peer_group_active (peer) ||
4801 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4802 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4803
4804 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004805 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004806 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004807 if (! peer_group_active (peer) ||
4808 g_peer->ttl != peer->ttl)
4809 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4810 VTY_NEWLINE);
4811
Nick Hilliardfa411a22011-03-23 15:33:17 +00004812 /* ttl-security hops */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004813 if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004814 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004815 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004816 peer->gtsm_hops, VTY_NEWLINE);
4817
hasso6ffd2072005-02-02 14:50:11 +00004818 /* disable-connected-check. */
4819 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004820 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004821 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4822 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004823
4824 /* Update-source. */
4825 if (peer->update_if)
4826 if (! peer_group_active (peer) || ! g_peer->update_if
4827 || strcmp (g_peer->update_if, peer->update_if) != 0)
4828 vty_out (vty, " neighbor %s update-source %s%s", addr,
4829 peer->update_if, VTY_NEWLINE);
4830 if (peer->update_source)
4831 if (! peer_group_active (peer) || ! g_peer->update_source
4832 || sockunion_cmp (g_peer->update_source,
4833 peer->update_source) != 0)
4834 vty_out (vty, " neighbor %s update-source %s%s", addr,
4835 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4836 VTY_NEWLINE);
4837
paul718e3742002-12-13 20:15:29 +00004838 /* advertisement-interval */
4839 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4840 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4841 addr, peer->v_routeadv, VTY_NEWLINE);
4842
4843 /* timers. */
4844 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4845 && ! peer_group_active (peer))
4846 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4847 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4848
4849 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4850 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4851 peer->connect, VTY_NEWLINE);
4852
4853 /* Default weight. */
4854 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4855 if (! peer_group_active (peer) ||
4856 g_peer->weight != peer->weight)
4857 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4858 VTY_NEWLINE);
4859
paul718e3742002-12-13 20:15:29 +00004860 /* Dynamic capability. */
4861 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4862 if (! peer_group_active (peer) ||
4863 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4864 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4865 VTY_NEWLINE);
4866
4867 /* dont capability negotiation. */
4868 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4869 if (! peer_group_active (peer) ||
4870 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4871 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4872 VTY_NEWLINE);
4873
4874 /* override capability negotiation. */
4875 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4876 if (! peer_group_active (peer) ||
4877 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4878 vty_out (vty, " neighbor %s override-capability%s", addr,
4879 VTY_NEWLINE);
4880
4881 /* strict capability negotiation. */
4882 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4883 if (! peer_group_active (peer) ||
4884 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4885 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4886 VTY_NEWLINE);
4887
4888 if (! peer_group_active (peer))
4889 {
4890 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4891 {
4892 if (peer->afc[AFI_IP][SAFI_UNICAST])
4893 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4894 }
4895 else
4896 {
4897 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4898 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4899 }
4900 }
4901 }
4902
4903
4904 /************************************
4905 ****** Per AF to the neighbor ******
4906 ************************************/
4907
4908 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4909 {
4910 if (peer->af_group[afi][safi])
4911 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4912 peer->group->name, VTY_NEWLINE);
4913 else
4914 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4915 }
4916
4917 /* ORF capability. */
4918 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4919 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4920 if (! peer->af_group[afi][safi])
4921 {
4922 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4923
4924 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4925 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4926 vty_out (vty, " both");
4927 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4928 vty_out (vty, " send");
4929 else
4930 vty_out (vty, " receive");
4931 vty_out (vty, "%s", VTY_NEWLINE);
4932 }
4933
4934 /* Route reflector client. */
4935 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4936 && ! peer->af_group[afi][safi])
4937 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4938 VTY_NEWLINE);
4939
4940 /* Nexthop self. */
4941 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4942 && ! peer->af_group[afi][safi])
4943 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4944
4945 /* Remove private AS. */
4946 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4947 && ! peer->af_group[afi][safi])
4948 vty_out (vty, " neighbor %s remove-private-AS%s",
4949 addr, VTY_NEWLINE);
4950
4951 /* send-community print. */
4952 if (! peer->af_group[afi][safi])
4953 {
4954 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4955 {
4956 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4957 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4958 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4959 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4960 vty_out (vty, " neighbor %s send-community extended%s",
4961 addr, VTY_NEWLINE);
4962 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4963 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4964 }
4965 else
4966 {
4967 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4968 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4969 vty_out (vty, " no neighbor %s send-community both%s",
4970 addr, VTY_NEWLINE);
4971 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4972 vty_out (vty, " no neighbor %s send-community extended%s",
4973 addr, VTY_NEWLINE);
4974 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4975 vty_out (vty, " no neighbor %s send-community%s",
4976 addr, VTY_NEWLINE);
4977 }
4978 }
4979
4980 /* Default information */
4981 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4982 && ! peer->af_group[afi][safi])
4983 {
4984 vty_out (vty, " neighbor %s default-originate", addr);
4985 if (peer->default_rmap[afi][safi].name)
4986 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4987 vty_out (vty, "%s", VTY_NEWLINE);
4988 }
4989
4990 /* Soft reconfiguration inbound. */
4991 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4992 if (! peer->af_group[afi][safi] ||
4993 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4994 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4995 VTY_NEWLINE);
4996
4997 /* maximum-prefix. */
4998 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4999 if (! peer->af_group[afi][safi]
5000 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005001 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005002 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5003 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005004 {
hasso0a486e52005-02-01 20:57:17 +00005005 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5006 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5007 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5008 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5009 vty_out (vty, " warning-only");
5010 if (peer->pmax_restart[afi][safi])
5011 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5012 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005013 }
paul718e3742002-12-13 20:15:29 +00005014
5015 /* Route server client. */
5016 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5017 && ! peer->af_group[afi][safi])
5018 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5019
Dylan Hall3cf12882011-10-27 15:28:17 +04005020 /* Nexthop-local unchanged. */
5021 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5022 && ! peer->af_group[afi][safi])
5023 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5024
paul718e3742002-12-13 20:15:29 +00005025 /* Allow AS in. */
5026 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5027 if (! peer_group_active (peer)
5028 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5029 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5030 {
5031 if (peer->allowas_in[afi][safi] == 3)
5032 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5033 else
5034 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5035 peer->allowas_in[afi][safi], VTY_NEWLINE);
5036 }
5037
5038 /* Filter. */
5039 bgp_config_write_filter (vty, peer, afi, safi);
5040
5041 /* atribute-unchanged. */
5042 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5043 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5044 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5045 && ! peer->af_group[afi][safi])
5046 {
5047 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5048 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5049 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5050 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5051 else
5052 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5053 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5054 " as-path" : "",
5055 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5056 " next-hop" : "",
5057 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5058 " med" : "", VTY_NEWLINE);
5059 }
5060}
5061
5062/* Display "address-family" configuration header. */
5063void
5064bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5065 int *write)
5066{
5067 if (*write)
5068 return;
5069
5070 if (afi == AFI_IP && safi == SAFI_UNICAST)
5071 return;
5072
5073 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5074
5075 if (afi == AFI_IP)
5076 {
5077 if (safi == SAFI_MULTICAST)
5078 vty_out (vty, "ipv4 multicast");
5079 else if (safi == SAFI_MPLS_VPN)
5080 vty_out (vty, "vpnv4 unicast");
5081 }
5082 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005083 {
5084 vty_out (vty, "ipv6");
5085
5086 if (safi == SAFI_MULTICAST)
5087 vty_out (vty, " multicast");
5088 }
paul718e3742002-12-13 20:15:29 +00005089
5090 vty_out (vty, "%s", VTY_NEWLINE);
5091
5092 *write = 1;
5093}
5094
5095/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005096static int
paul718e3742002-12-13 20:15:29 +00005097bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5098 safi_t safi)
5099{
5100 int write = 0;
5101 struct peer *peer;
5102 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005104
5105 bgp_config_write_network (vty, bgp, afi, safi, &write);
5106
5107 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5108
paul1eb8ef22005-04-07 07:30:20 +00005109 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005110 {
5111 if (group->conf->afc[afi][safi])
5112 {
5113 bgp_config_write_family_header (vty, afi, safi, &write);
5114 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5115 }
5116 }
paul1eb8ef22005-04-07 07:30:20 +00005117 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005118 {
5119 if (peer->afc[afi][safi])
5120 {
5121 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5122 {
5123 bgp_config_write_family_header (vty, afi, safi, &write);
5124 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5125 }
5126 }
5127 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005128
5129 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5130
paul718e3742002-12-13 20:15:29 +00005131 if (write)
5132 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5133
5134 return write;
5135}
5136
5137int
5138bgp_config_write (struct vty *vty)
5139{
5140 int write = 0;
5141 struct bgp *bgp;
5142 struct peer_group *group;
5143 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005144 struct listnode *node, *nnode;
5145 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005146
5147 /* BGP Multiple instance. */
5148 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5149 {
5150 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5151 write++;
5152 }
5153
5154 /* BGP Config type. */
5155 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5156 {
5157 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5158 write++;
5159 }
5160
5161 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005162 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005163 {
5164 if (write)
5165 vty_out (vty, "!%s", VTY_NEWLINE);
5166
5167 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005168 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005169
5170 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5171 {
5172 if (bgp->name)
5173 vty_out (vty, " view %s", bgp->name);
5174 }
5175 vty_out (vty, "%s", VTY_NEWLINE);
5176
5177 /* No Synchronization */
5178 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5179 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5180
5181 /* BGP fast-external-failover. */
5182 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5183 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5184
5185 /* BGP router ID. */
5186 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5187 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5188 VTY_NEWLINE);
5189
paul848973c2003-08-13 00:32:49 +00005190 /* BGP log-neighbor-changes. */
5191 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5192 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5193
paul718e3742002-12-13 20:15:29 +00005194 /* BGP configuration. */
5195 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5196 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5197
5198 /* BGP default ipv4-unicast. */
5199 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5200 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5201
5202 /* BGP default local-preference. */
5203 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5204 vty_out (vty, " bgp default local-preference %d%s",
5205 bgp->default_local_pref, VTY_NEWLINE);
5206
5207 /* BGP client-to-client reflection. */
5208 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5209 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5210
5211 /* BGP cluster ID. */
5212 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5213 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5214 VTY_NEWLINE);
5215
hassoe0701b72004-05-20 09:19:34 +00005216 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005217 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005218 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5219 VTY_NEWLINE);
5220
5221 /* Confederation peer */
5222 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005223 {
hassoe0701b72004-05-20 09:19:34 +00005224 int i;
paul718e3742002-12-13 20:15:29 +00005225
hassoe0701b72004-05-20 09:19:34 +00005226 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005227
hassoe0701b72004-05-20 09:19:34 +00005228 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005229 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005230
hassoe0701b72004-05-20 09:19:34 +00005231 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005232 }
5233
5234 /* BGP enforce-first-as. */
5235 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5236 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5237
5238 /* BGP deterministic-med. */
5239 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5240 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005241
5242 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005243 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5244 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5245 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005246 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5247 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5248
paul718e3742002-12-13 20:15:29 +00005249 /* BGP bestpath method. */
5250 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5251 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005252 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5253 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005254 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5255 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5256 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5257 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5258 {
5259 vty_out (vty, " bgp bestpath med");
5260 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5261 vty_out (vty, " confed");
5262 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5263 vty_out (vty, " missing-as-worst");
5264 vty_out (vty, "%s", VTY_NEWLINE);
5265 }
5266
5267 /* BGP network import check. */
5268 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5269 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5270
5271 /* BGP scan interval. */
5272 bgp_config_write_scan_time (vty);
5273
5274 /* BGP flag dampening. */
5275 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5276 BGP_CONFIG_DAMPENING))
5277 bgp_config_write_damp (vty);
5278
5279 /* BGP static route configuration. */
5280 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5281
5282 /* BGP redistribute configuration. */
5283 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5284
5285 /* BGP timers configuration. */
5286 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5287 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5288 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5289 bgp->default_holdtime, VTY_NEWLINE);
5290
5291 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005292 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005293 {
5294 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5295 }
5296
5297 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005298 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005299 {
5300 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5301 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5302 }
5303
Josh Bailey165b5ff2011-07-20 20:43:22 -07005304 /* maximum-paths */
5305 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5306
paul718e3742002-12-13 20:15:29 +00005307 /* Distance configuration. */
5308 bgp_config_write_distance (vty, bgp);
5309
5310 /* No auto-summary */
5311 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5312 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5313
5314 /* IPv4 multicast configuration. */
5315 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5316
5317 /* IPv4 VPN configuration. */
5318 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5319
5320 /* IPv6 unicast configuration. */
5321 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5322
Paul Jakma37a217a2007-04-10 19:20:29 +00005323 /* IPv6 multicast configuration. */
5324 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5325
paul718e3742002-12-13 20:15:29 +00005326 write++;
5327 }
5328 return write;
5329}
5330
5331void
paul94f2b392005-06-28 12:44:16 +00005332bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005333{
5334 memset (&bgp_master, 0, sizeof (struct bgp_master));
5335
5336 bm = &bgp_master;
5337 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005338 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005339 bm->port = BGP_PORT_DEFAULT;
5340 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005341 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005342}
paul200df112005-06-01 11:17:05 +00005343
paul718e3742002-12-13 20:15:29 +00005344
Paul Jakma7621f332012-05-01 16:24:35 +01005345int
5346bgp_socket_init (void)
5347{
5348 /* Create BGP server socket */
5349 if (bgp_socket (bm->port, bm->address) < 0)
5350 return BGP_ERR_INVALID_VALUE;
5351 return 0;
5352}
5353
paul718e3742002-12-13 20:15:29 +00005354void
paul94f2b392005-06-28 12:44:16 +00005355bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005356{
paul718e3742002-12-13 20:15:29 +00005357 /* BGP VTY commands installation. */
5358 bgp_vty_init ();
5359
paul718e3742002-12-13 20:15:29 +00005360 /* Init zebra. */
5361 bgp_zebra_init ();
5362
5363 /* BGP inits. */
5364 bgp_attr_init ();
5365 bgp_debug_init ();
5366 bgp_dump_init ();
5367 bgp_route_init ();
5368 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005369 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005370 bgp_scan_init ();
5371 bgp_mplsvpn_init ();
5372
5373 /* Access list initialize. */
5374 access_list_init ();
5375 access_list_add_hook (peer_distribute_update);
5376 access_list_delete_hook (peer_distribute_update);
5377
5378 /* Filter list initialize. */
5379 bgp_filter_init ();
5380 as_list_add_hook (peer_aslist_update);
5381 as_list_delete_hook (peer_aslist_update);
5382
5383 /* Prefix list initialize.*/
5384 prefix_list_init ();
5385 prefix_list_add_hook (peer_prefix_list_update);
5386 prefix_list_delete_hook (peer_prefix_list_update);
5387
5388 /* Community list initialize. */
5389 bgp_clist = community_list_init ();
5390
5391#ifdef HAVE_SNMP
5392 bgp_snmp_init ();
5393#endif /* HAVE_SNMP */
5394}
paul545acaf2004-04-20 15:13:15 +00005395
5396void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005397bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005398{
paul545acaf2004-04-20 15:13:15 +00005399 struct bgp *bgp;
5400 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005401 struct listnode *node, *nnode;
5402 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005403
paul1eb8ef22005-04-07 07:30:20 +00005404 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5405 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005406 if (peer->status == Established)
5407 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5408 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005409
paul545acaf2004-04-20 15:13:15 +00005410 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005411
paule210cf92005-06-15 19:15:35 +00005412 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005413 {
5414 work_queue_free (bm->process_main_queue);
5415 bm->process_main_queue = NULL;
5416 }
paule210cf92005-06-15 19:15:35 +00005417 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005418 {
5419 work_queue_free (bm->process_rsclient_queue);
5420 bm->process_rsclient_queue = NULL;
5421 }
paul545acaf2004-04-20 15:13:15 +00005422}