blob: 9c8eda8894b8e17bb95c1d89eb54a851adf94778 [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 {
204 if (peer_sort (peer) != BGP_PEER_IBGP)
205 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 {
232 if (peer_sort (peer) != BGP_PEER_IBGP)
233 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
648/* Check peer's AS number and determin is this peer IBGP or EBGP */
649int
650peer_sort (struct peer *peer)
651{
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
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100699static void
paul200df112005-06-01 11:17:05 +0000700peer_free (struct peer *peer)
701{
Paul Jakmaca058a32006-09-14 02:58:49 +0000702 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700703
704 bgp_unlock(peer->bgp);
705
Paul Jakmaca058a32006-09-14 02:58:49 +0000706 /* this /ought/ to have been done already through bgp_stop earlier,
707 * but just to be sure..
708 */
709 bgp_timer_set (peer);
710 BGP_READ_OFF (peer->t_read);
711 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000712 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000713
paul200df112005-06-01 11:17:05 +0000714 if (peer->desc)
715 XFREE (MTYPE_PEER_DESC, peer->desc);
716
717 /* Free allocated host character. */
718 if (peer->host)
719 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
720
721 /* Update source configuration. */
722 if (peer->update_source)
723 sockunion_free (peer->update_source);
724
725 if (peer->update_if)
726 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000727
728 if (peer->clear_node_queue)
729 work_queue_free (peer->clear_node_queue);
730
Paul Jakmaca058a32006-09-14 02:58:49 +0000731 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000732 memset (peer, 0, sizeof (struct peer));
733
734 XFREE (MTYPE_BGP_PEER, peer);
735}
736
737/* increase reference count on a struct peer */
738struct peer *
739peer_lock (struct peer *peer)
740{
741 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000742
paul200df112005-06-01 11:17:05 +0000743 peer->lock++;
744
745 return peer;
746}
747
748/* decrease reference count on a struct peer
749 * struct peer is freed and NULL returned if last reference
750 */
751struct peer *
752peer_unlock (struct peer *peer)
753{
754 assert (peer && (peer->lock > 0));
755
756 peer->lock--;
757
758 if (peer->lock == 0)
759 {
760#if 0
761 zlog_debug ("unlocked and freeing");
762 zlog_backtrace (LOG_DEBUG);
763#endif
764 peer_free (peer);
765 return NULL;
766 }
767
768#if 0
769 if (peer->lock == 1)
770 {
771 zlog_debug ("unlocked to 1");
772 zlog_backtrace (LOG_DEBUG);
773 }
774#endif
775
776 return peer;
777}
778
779/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000780static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000781peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000782{
783 afi_t afi;
784 safi_t safi;
785 struct peer *peer;
786 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000787
788 /* bgp argument is absolutely required */
789 assert (bgp);
790 if (!bgp)
791 return NULL;
792
paul718e3742002-12-13 20:15:29 +0000793 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000794 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000795
796 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000797 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000798 peer->v_start = BGP_INIT_START_TIMER;
799 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
800 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
801 peer->status = Idle;
802 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000803 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000804 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000805 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000806 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700807 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000808
809 /* Set default flags. */
810 for (afi = AFI_IP; afi < AFI_MAX; afi++)
811 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
812 {
813 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
814 {
815 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
816 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
817 }
818 peer->orf_plist[afi][safi] = NULL;
819 }
820 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
821
822 /* Create buffers. */
823 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
824 peer->obuf = stream_fifo_new ();
825 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
826
827 bgp_sync_init (peer);
828
829 /* Get service port number. */
830 sp = getservbyname ("bgp", "tcp");
831 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
832
833 return peer;
834}
835
836/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000837static struct peer *
paul718e3742002-12-13 20:15:29 +0000838peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
839 as_t remote_as, afi_t afi, safi_t safi)
840{
841 int active;
842 struct peer *peer;
843 char buf[SU_ADDRSTRLEN];
844
Paul Jakma6f585442006-10-22 19:13:07 +0000845 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000846 peer->su = *su;
847 peer->local_as = local_as;
848 peer->as = remote_as;
849 peer->local_id = bgp->router_id;
850 peer->v_holdtime = bgp->default_holdtime;
851 peer->v_keepalive = bgp->default_keepalive;
852 if (peer_sort (peer) == BGP_PEER_IBGP)
853 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
854 else
855 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000856
857 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000858 listnode_add_sort (bgp->peer, peer);
859
860 active = peer_active (peer);
861
862 if (afi && safi)
863 peer->afc[afi][safi] = 1;
864
Stephen Hemminger65957882010-01-15 16:22:10 +0300865 /* Last read and reset time set */
866 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000867
paul718e3742002-12-13 20:15:29 +0000868 /* Default TTL set. */
869 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
870
871 /* Make peer's address string. */
872 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000873 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000874
875 /* Set up peer's events and timers. */
876 if (! active && peer_active (peer))
877 bgp_timer_set (peer);
878
879 return peer;
880}
881
pauleb821182004-05-01 08:44:08 +0000882/* Make accept BGP peer. Called from bgp_accept (). */
883struct peer *
884peer_create_accept (struct bgp *bgp)
885{
886 struct peer *peer;
887
Paul Jakma6f585442006-10-22 19:13:07 +0000888 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000889
890 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000891 listnode_add_sort (bgp->peer, peer);
892
893 return peer;
894}
895
paul718e3742002-12-13 20:15:29 +0000896/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000897static void
paul718e3742002-12-13 20:15:29 +0000898peer_as_change (struct peer *peer, as_t as)
899{
900 int type;
901
902 /* Stop peer. */
903 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
904 {
905 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000906 {
907 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
908 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
909 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
910 }
paul718e3742002-12-13 20:15:29 +0000911 else
912 BGP_EVENT_ADD (peer, BGP_Stop);
913 }
914 type = peer_sort (peer);
915 peer->as = as;
916
paul848973c2003-08-13 00:32:49 +0000917 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
918 && ! bgp_confederation_peers_check (peer->bgp, as)
919 && peer->bgp->as != as)
920 peer->local_as = peer->bgp->confed_id;
921 else
922 peer->local_as = peer->bgp->as;
923
paul718e3742002-12-13 20:15:29 +0000924 /* Advertisement-interval reset */
925 if (peer_sort (peer) == BGP_PEER_IBGP)
926 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
927 else
928 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
929
930 /* TTL reset */
931 if (peer_sort (peer) == BGP_PEER_IBGP)
932 peer->ttl = 255;
933 else if (type == BGP_PEER_IBGP)
934 peer->ttl = 1;
935
936 /* reflector-client reset */
937 if (peer_sort (peer) != BGP_PEER_IBGP)
938 {
939 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
940 PEER_FLAG_REFLECTOR_CLIENT);
941 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
942 PEER_FLAG_REFLECTOR_CLIENT);
943 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
944 PEER_FLAG_REFLECTOR_CLIENT);
945 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
946 PEER_FLAG_REFLECTOR_CLIENT);
947 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
948 PEER_FLAG_REFLECTOR_CLIENT);
949 }
950
951 /* local-as reset */
952 if (peer_sort (peer) != BGP_PEER_EBGP)
953 {
954 peer->change_local_as = 0;
955 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
956 }
957}
958
959/* If peer does not exist, create new one. If peer already exists,
960 set AS number to the peer. */
961int
962peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
963 afi_t afi, safi_t safi)
964{
965 struct peer *peer;
966 as_t local_as;
967
968 peer = peer_lookup (bgp, su);
969
970 if (peer)
971 {
972 /* When this peer is a member of peer-group. */
973 if (peer->group)
974 {
975 if (peer->group->conf->as)
976 {
977 /* Return peer group's AS number. */
978 *as = peer->group->conf->as;
979 return BGP_ERR_PEER_GROUP_MEMBER;
980 }
981 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
982 {
983 if (bgp->as != *as)
984 {
985 *as = peer->as;
986 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
987 }
988 }
989 else
990 {
991 if (bgp->as == *as)
992 {
993 *as = peer->as;
994 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
995 }
996 }
997 }
998
999 /* Existing peer's AS number change. */
1000 if (peer->as != *as)
1001 peer_as_change (peer, *as);
1002 }
1003 else
1004 {
1005
1006 /* If the peer is not part of our confederation, and its not an
1007 iBGP peer then spoof the source AS */
1008 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1009 && ! bgp_confederation_peers_check (bgp, *as)
1010 && bgp->as != *as)
1011 local_as = bgp->confed_id;
1012 else
1013 local_as = bgp->as;
1014
1015 /* If this is IPv4 unicast configuration and "no bgp default
1016 ipv4-unicast" is specified. */
1017
1018 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1019 && afi == AFI_IP && safi == SAFI_UNICAST)
1020 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1021 else
1022 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1023 }
1024
1025 return 0;
1026}
1027
1028/* Activate the peer or peer group for specified AFI and SAFI. */
1029int
1030peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1031{
1032 int active;
1033
1034 if (peer->afc[afi][safi])
1035 return 0;
1036
1037 /* Activate the address family configuration. */
1038 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1039 peer->afc[afi][safi] = 1;
1040 else
1041 {
1042 active = peer_active (peer);
1043
1044 peer->afc[afi][safi] = 1;
1045
1046 if (! active && peer_active (peer))
1047 bgp_timer_set (peer);
1048 else
1049 {
1050 if (peer->status == Established)
1051 {
1052 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1053 {
1054 peer->afc_adv[afi][safi] = 1;
1055 bgp_capability_send (peer, afi, safi,
1056 CAPABILITY_CODE_MP,
1057 CAPABILITY_ACTION_SET);
1058 if (peer->afc_recv[afi][safi])
1059 {
1060 peer->afc_nego[afi][safi] = 1;
1061 bgp_announce_route (peer, afi, safi);
1062 }
1063 }
1064 else
hassoe0701b72004-05-20 09:19:34 +00001065 {
1066 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1067 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1068 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1069 }
paul718e3742002-12-13 20:15:29 +00001070 }
1071 }
1072 }
1073 return 0;
1074}
1075
1076int
1077peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1078{
1079 struct peer_group *group;
1080 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001081 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001082
1083 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1084 {
1085 group = peer->group;
1086
paul1eb8ef22005-04-07 07:30:20 +00001087 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001088 {
1089 if (peer1->af_group[afi][safi])
1090 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1091 }
1092 }
1093 else
1094 {
1095 if (peer->af_group[afi][safi])
1096 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1097 }
1098
1099 if (! peer->afc[afi][safi])
1100 return 0;
1101
1102 /* De-activate the address family configuration. */
1103 peer->afc[afi][safi] = 0;
1104 peer_af_flag_reset (peer, afi, safi);
1105
1106 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1107 {
1108 if (peer->status == Established)
1109 {
1110 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1111 {
1112 peer->afc_adv[afi][safi] = 0;
1113 peer->afc_nego[afi][safi] = 0;
1114
1115 if (peer_active_nego (peer))
1116 {
1117 bgp_capability_send (peer, afi, safi,
1118 CAPABILITY_CODE_MP,
1119 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001120 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001121 peer->pcount[afi][safi] = 0;
1122 }
1123 else
hassoe0701b72004-05-20 09:19:34 +00001124 {
1125 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1126 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1127 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1128 }
paul718e3742002-12-13 20:15:29 +00001129 }
1130 else
hassoe0701b72004-05-20 09:19:34 +00001131 {
1132 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1133 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1134 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1135 }
paul718e3742002-12-13 20:15:29 +00001136 }
1137 }
1138 return 0;
1139}
1140
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001141static void
hasso93406d82005-02-02 14:40:33 +00001142peer_nsf_stop (struct peer *peer)
1143{
1144 afi_t afi;
1145 safi_t safi;
1146
1147 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1148 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1149
1150 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001151 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001152 peer->nsf[afi][safi] = 0;
1153
1154 if (peer->t_gr_restart)
1155 {
1156 BGP_TIMER_OFF (peer->t_gr_restart);
1157 if (BGP_DEBUG (events, EVENTS))
1158 zlog_debug ("%s graceful restart timer stopped", peer->host);
1159 }
1160 if (peer->t_gr_stale)
1161 {
1162 BGP_TIMER_OFF (peer->t_gr_stale);
1163 if (BGP_DEBUG (events, EVENTS))
1164 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1165 }
1166 bgp_clear_route_all (peer);
1167}
1168
Paul Jakmaca058a32006-09-14 02:58:49 +00001169/* Delete peer from confguration.
1170 *
1171 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1172 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1173 *
1174 * This function /should/ take care to be idempotent, to guard against
1175 * it being called multiple times through stray events that come in
1176 * that happen to result in this function being called again. That
1177 * said, getting here for a "Deleted" peer is a bug in the neighbour
1178 * FSM.
1179 */
paul718e3742002-12-13 20:15:29 +00001180int
1181peer_delete (struct peer *peer)
1182{
1183 int i;
1184 afi_t afi;
1185 safi_t safi;
1186 struct bgp *bgp;
1187 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001188 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001189
Paul Jakmaca058a32006-09-14 02:58:49 +00001190 assert (peer->status != Deleted);
1191
paul718e3742002-12-13 20:15:29 +00001192 bgp = peer->bgp;
1193
hasso93406d82005-02-02 14:40:33 +00001194 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1195 peer_nsf_stop (peer);
1196
Chris Caputo228da422009-07-18 05:44:03 +00001197 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001198 relationship. */
1199 if (peer->group)
1200 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001201 if ((pn = listnode_lookup (peer->group->peer, peer)))
1202 {
1203 peer = peer_unlock (peer); /* group->peer list reference */
1204 list_delete_node (peer->group->peer, pn);
1205 }
paul718e3742002-12-13 20:15:29 +00001206 peer->group = NULL;
1207 }
paul200df112005-06-01 11:17:05 +00001208
paul718e3742002-12-13 20:15:29 +00001209 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001210 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1211 * executed after peer structure is deleted.
1212 */
hassoe0701b72004-05-20 09:19:34 +00001213 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001214 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001215 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001216
1217 /* Password configuration */
1218 if (peer->password)
1219 {
1220 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1221 peer->password = NULL;
1222
1223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1224 bgp_md5_set (peer);
1225 }
1226
Paul Jakmaca058a32006-09-14 02:58:49 +00001227 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001228
paul718e3742002-12-13 20:15:29 +00001229 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001230 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1231 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001232 {
Chris Caputo228da422009-07-18 05:44:03 +00001233 peer_unlock (peer); /* bgp peer list reference */
1234 list_delete_node (bgp->peer, pn);
1235 }
paul200df112005-06-01 11:17:05 +00001236
Chris Caputo228da422009-07-18 05:44:03 +00001237 if (peer_rsclient_active (peer)
1238 && (pn = listnode_lookup (bgp->rsclient, peer)))
1239 {
1240 peer_unlock (peer); /* rsclient list reference */
1241 list_delete_node (bgp->rsclient, pn);
1242
1243 /* Clear our own rsclient ribs. */
1244 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1245 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1246 if (CHECK_FLAG(peer->af_flags[afi][safi],
1247 PEER_FLAG_RSERVER_CLIENT))
1248 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001249 }
1250
1251 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1252 member of a peer_group. */
1253 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1254 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1255 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001256 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001257
paul200df112005-06-01 11:17:05 +00001258 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001259 if (peer->ibuf)
1260 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001261 if (peer->obuf)
1262 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001263 if (peer->work)
1264 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001265 peer->obuf = NULL;
1266 peer->work = peer->ibuf = NULL;
1267
paul718e3742002-12-13 20:15:29 +00001268 /* Local and remote addresses. */
1269 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001270 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001271 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001272 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001273 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001274
paul718e3742002-12-13 20:15:29 +00001275 /* Free filter related memory. */
1276 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1277 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1278 {
1279 filter = &peer->filter[afi][safi];
1280
1281 for (i = FILTER_IN; i < FILTER_MAX; i++)
1282 {
1283 if (filter->dlist[i].name)
1284 free (filter->dlist[i].name);
1285 if (filter->plist[i].name)
1286 free (filter->plist[i].name);
1287 if (filter->aslist[i].name)
1288 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001289
1290 filter->dlist[i].name = NULL;
1291 filter->plist[i].name = NULL;
1292 filter->aslist[i].name = NULL;
1293 }
1294 for (i = RMAP_IN; i < RMAP_MAX; i++)
1295 {
paul718e3742002-12-13 20:15:29 +00001296 if (filter->map[i].name)
1297 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001298 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001299 }
1300
1301 if (filter->usmap.name)
1302 free (filter->usmap.name);
1303
1304 if (peer->default_rmap[afi][safi].name)
1305 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001306
1307 filter->usmap.name = NULL;
1308 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001309 }
paul200df112005-06-01 11:17:05 +00001310
1311 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001312
1313 return 0;
1314}
1315
paul94f2b392005-06-28 12:44:16 +00001316static int
paul718e3742002-12-13 20:15:29 +00001317peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1318{
1319 return strcmp (g1->name, g2->name);
1320}
1321
1322/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001323static int
paul718e3742002-12-13 20:15:29 +00001324peer_group_active (struct peer *peer)
1325{
1326 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1327 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1328 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1329 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1330 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1331 return 1;
1332 return 0;
1333}
1334
1335/* Peer group cofiguration. */
1336static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001337peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001338{
1339 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1340 sizeof (struct peer_group));
1341}
1342
paul94f2b392005-06-28 12:44:16 +00001343static void
paul718e3742002-12-13 20:15:29 +00001344peer_group_free (struct peer_group *group)
1345{
1346 XFREE (MTYPE_PEER_GROUP, group);
1347}
1348
1349struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001350peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001351{
1352 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001353 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001354
paul1eb8ef22005-04-07 07:30:20 +00001355 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001356 {
1357 if (strcmp (group->name, name) == 0)
1358 return group;
1359 }
1360 return NULL;
1361}
1362
1363struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001364peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001365{
1366 struct peer_group *group;
1367
1368 group = peer_group_lookup (bgp, name);
1369 if (group)
1370 return group;
1371
1372 group = peer_group_new ();
1373 group->bgp = bgp;
1374 group->name = strdup (name);
1375 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001376 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001377 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1378 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001379 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001380 group->conf->group = group;
1381 group->conf->as = 0;
1382 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001383 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001384 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1385 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1386 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1387 group->conf->keepalive = 0;
1388 group->conf->holdtime = 0;
1389 group->conf->connect = 0;
1390 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1391 listnode_add_sort (bgp->group, group);
1392
1393 return 0;
1394}
1395
paul94f2b392005-06-28 12:44:16 +00001396static void
paul718e3742002-12-13 20:15:29 +00001397peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1398 afi_t afi, safi_t safi)
1399{
1400 int in = FILTER_IN;
1401 int out = FILTER_OUT;
1402 struct peer *conf;
1403 struct bgp_filter *pfilter;
1404 struct bgp_filter *gfilter;
1405
1406 conf = group->conf;
1407 pfilter = &peer->filter[afi][safi];
1408 gfilter = &conf->filter[afi][safi];
1409
1410 /* remote-as */
1411 if (conf->as)
1412 peer->as = conf->as;
1413
1414 /* remote-as */
1415 if (conf->change_local_as)
1416 peer->change_local_as = conf->change_local_as;
1417
1418 /* TTL */
1419 peer->ttl = conf->ttl;
1420
Nick Hilliardfa411a22011-03-23 15:33:17 +00001421 /* GTSM hops */
1422 peer->gtsm_hops = conf->gtsm_hops;
1423
paul718e3742002-12-13 20:15:29 +00001424 /* Weight */
1425 peer->weight = conf->weight;
1426
1427 /* peer flags apply */
1428 peer->flags = conf->flags;
1429 /* peer af_flags apply */
1430 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1431 /* peer config apply */
1432 peer->config = conf->config;
1433
1434 /* peer timers apply */
1435 peer->holdtime = conf->holdtime;
1436 peer->keepalive = conf->keepalive;
1437 peer->connect = conf->connect;
1438 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1439 peer->v_connect = conf->connect;
1440 else
1441 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1442
1443 /* advertisement-interval reset */
1444 if (peer_sort (peer) == BGP_PEER_IBGP)
1445 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1446 else
1447 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1448
Paul Jakma0df7c912008-07-21 21:02:49 +00001449 /* password apply */
1450 if (peer->password)
1451 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1452
1453 if (conf->password)
1454 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1455 else
1456 peer->password = NULL;
1457
1458 bgp_md5_set (peer);
1459
paul718e3742002-12-13 20:15:29 +00001460 /* maximum-prefix */
1461 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001462 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001463 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001464
1465 /* allowas-in */
1466 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1467
paulfee0f4c2004-09-13 05:12:46 +00001468 /* route-server-client */
1469 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1470 {
1471 /* Make peer's RIB point to group's RIB. */
1472 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1473
1474 /* Import policy. */
1475 if (pfilter->map[RMAP_IMPORT].name)
1476 free (pfilter->map[RMAP_IMPORT].name);
1477 if (gfilter->map[RMAP_IMPORT].name)
1478 {
1479 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1480 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1481 }
1482 else
1483 {
1484 pfilter->map[RMAP_IMPORT].name = NULL;
1485 pfilter->map[RMAP_IMPORT].map = NULL;
1486 }
1487
1488 /* Export policy. */
1489 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1490 {
1491 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1492 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1493 }
1494 }
1495
paul718e3742002-12-13 20:15:29 +00001496 /* default-originate route-map */
1497 if (conf->default_rmap[afi][safi].name)
1498 {
1499 if (peer->default_rmap[afi][safi].name)
1500 free (peer->default_rmap[afi][safi].name);
1501 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1502 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1503 }
1504
1505 /* update-source apply */
1506 if (conf->update_source)
1507 {
1508 if (peer->update_source)
1509 sockunion_free (peer->update_source);
1510 if (peer->update_if)
1511 {
1512 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1513 peer->update_if = NULL;
1514 }
1515 peer->update_source = sockunion_dup (conf->update_source);
1516 }
1517 else if (conf->update_if)
1518 {
1519 if (peer->update_if)
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 if (peer->update_source)
1522 {
1523 sockunion_free (peer->update_source);
1524 peer->update_source = NULL;
1525 }
1526 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1527 }
1528
1529 /* inbound filter apply */
1530 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1531 {
1532 if (pfilter->dlist[in].name)
1533 free (pfilter->dlist[in].name);
1534 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1535 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1536 }
1537 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1538 {
1539 if (pfilter->plist[in].name)
1540 free (pfilter->plist[in].name);
1541 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1542 pfilter->plist[in].plist = gfilter->plist[in].plist;
1543 }
1544 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1545 {
1546 if (pfilter->aslist[in].name)
1547 free (pfilter->aslist[in].name);
1548 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1549 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1550 }
paulfee0f4c2004-09-13 05:12:46 +00001551 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001552 {
paulfee0f4c2004-09-13 05:12:46 +00001553 if (pfilter->map[RMAP_IN].name)
1554 free (pfilter->map[RMAP_IN].name);
1555 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1556 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001557 }
1558
1559 /* outbound filter apply */
1560 if (gfilter->dlist[out].name)
1561 {
1562 if (pfilter->dlist[out].name)
1563 free (pfilter->dlist[out].name);
1564 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1565 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1566 }
1567 else
1568 {
1569 if (pfilter->dlist[out].name)
1570 free (pfilter->dlist[out].name);
1571 pfilter->dlist[out].name = NULL;
1572 pfilter->dlist[out].alist = NULL;
1573 }
1574 if (gfilter->plist[out].name)
1575 {
1576 if (pfilter->plist[out].name)
1577 free (pfilter->plist[out].name);
1578 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1579 pfilter->plist[out].plist = gfilter->plist[out].plist;
1580 }
1581 else
1582 {
1583 if (pfilter->plist[out].name)
1584 free (pfilter->plist[out].name);
1585 pfilter->plist[out].name = NULL;
1586 pfilter->plist[out].plist = NULL;
1587 }
1588 if (gfilter->aslist[out].name)
1589 {
1590 if (pfilter->aslist[out].name)
1591 free (pfilter->aslist[out].name);
1592 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1593 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1594 }
1595 else
1596 {
1597 if (pfilter->aslist[out].name)
1598 free (pfilter->aslist[out].name);
1599 pfilter->aslist[out].name = NULL;
1600 pfilter->aslist[out].aslist = NULL;
1601 }
paulfee0f4c2004-09-13 05:12:46 +00001602 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001603 {
paulfee0f4c2004-09-13 05:12:46 +00001604 if (pfilter->map[RMAP_OUT].name)
1605 free (pfilter->map[RMAP_OUT].name);
1606 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1607 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001608 }
1609 else
1610 {
paulfee0f4c2004-09-13 05:12:46 +00001611 if (pfilter->map[RMAP_OUT].name)
1612 free (pfilter->map[RMAP_OUT].name);
1613 pfilter->map[RMAP_OUT].name = NULL;
1614 pfilter->map[RMAP_OUT].map = NULL;
1615 }
1616
1617 /* RS-client's import/export route-maps. */
1618 if (gfilter->map[RMAP_IMPORT].name)
1619 {
1620 if (pfilter->map[RMAP_IMPORT].name)
1621 free (pfilter->map[RMAP_IMPORT].name);
1622 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1623 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1624 }
1625 else
1626 {
1627 if (pfilter->map[RMAP_IMPORT].name)
1628 free (pfilter->map[RMAP_IMPORT].name);
1629 pfilter->map[RMAP_IMPORT].name = NULL;
1630 pfilter->map[RMAP_IMPORT].map = NULL;
1631 }
1632 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1633 {
1634 if (pfilter->map[RMAP_EXPORT].name)
1635 free (pfilter->map[RMAP_EXPORT].name);
1636 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1637 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001638 }
1639
1640 if (gfilter->usmap.name)
1641 {
1642 if (pfilter->usmap.name)
1643 free (pfilter->usmap.name);
1644 pfilter->usmap.name = strdup (gfilter->usmap.name);
1645 pfilter->usmap.map = gfilter->usmap.map;
1646 }
1647 else
1648 {
1649 if (pfilter->usmap.name)
1650 free (pfilter->usmap.name);
1651 pfilter->usmap.name = NULL;
1652 pfilter->usmap.map = NULL;
1653 }
1654}
1655
1656/* Peer group's remote AS configuration. */
1657int
paulfd79ac92004-10-13 05:06:08 +00001658peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001659{
1660 struct peer_group *group;
1661 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001662 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001663
1664 group = peer_group_lookup (bgp, group_name);
1665 if (! group)
1666 return -1;
1667
1668 if (group->conf->as == *as)
1669 return 0;
1670
1671 /* When we setup peer-group AS number all peer group member's AS
1672 number must be updated to same number. */
1673 peer_as_change (group->conf, *as);
1674
paul1eb8ef22005-04-07 07:30:20 +00001675 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001676 {
1677 if (peer->as != *as)
1678 peer_as_change (peer, *as);
1679 }
1680
1681 return 0;
1682}
1683
1684int
1685peer_group_delete (struct peer_group *group)
1686{
1687 struct bgp *bgp;
1688 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001689 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001690
1691 bgp = group->bgp;
1692
paul1eb8ef22005-04-07 07:30:20 +00001693 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001694 {
1695 peer->group = NULL;
1696 peer_delete (peer);
1697 }
1698 list_delete (group->peer);
1699
1700 free (group->name);
1701 group->name = NULL;
1702
1703 group->conf->group = NULL;
1704 peer_delete (group->conf);
1705
1706 /* Delete from all peer_group list. */
1707 listnode_delete (bgp->group, group);
1708
1709 peer_group_free (group);
1710
1711 return 0;
1712}
1713
1714int
1715peer_group_remote_as_delete (struct peer_group *group)
1716{
1717 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001718 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001719
1720 if (! group->conf->as)
1721 return 0;
1722
paul1eb8ef22005-04-07 07:30:20 +00001723 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001724 {
1725 peer->group = NULL;
1726 peer_delete (peer);
1727 }
1728 list_delete_all_node (group->peer);
1729
1730 group->conf->as = 0;
1731
1732 return 0;
1733}
1734
1735/* Bind specified peer to peer group. */
1736int
1737peer_group_bind (struct bgp *bgp, union sockunion *su,
1738 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1739{
1740 struct peer *peer;
1741 int first_member = 0;
1742
1743 /* Check peer group's address family. */
1744 if (! group->conf->afc[afi][safi])
1745 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1746
1747 /* Lookup the peer. */
1748 peer = peer_lookup (bgp, su);
1749
1750 /* Create a new peer. */
1751 if (! peer)
1752 {
1753 if (! group->conf->as)
1754 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1755
1756 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1757 peer->group = group;
1758 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001759
Paul Jakmaca058a32006-09-14 02:58:49 +00001760 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001761 listnode_add (group->peer, peer);
1762 peer_group2peer_config_copy (group, peer, afi, safi);
1763
1764 return 0;
1765 }
1766
1767 /* When the peer already belongs to peer group, check the consistency. */
1768 if (peer->af_group[afi][safi])
1769 {
1770 if (strcmp (peer->group->name, group->name) != 0)
1771 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1772
1773 return 0;
1774 }
1775
1776 /* Check current peer group configuration. */
1777 if (peer_group_active (peer)
1778 && strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_MISMATCH;
1780
1781 if (! group->conf->as)
1782 {
1783 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1784 && peer_sort (group->conf) != peer_sort (peer))
1785 {
1786 if (as)
1787 *as = peer->as;
1788 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1789 }
1790
1791 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1792 first_member = 1;
1793 }
1794
1795 peer->af_group[afi][safi] = 1;
1796 peer->afc[afi][safi] = 1;
1797 if (! peer->group)
1798 {
1799 peer->group = group;
paul200df112005-06-01 11:17:05 +00001800
Paul Jakmaca058a32006-09-14 02:58:49 +00001801 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001802 listnode_add (group->peer, peer);
1803 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001804 else
1805 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001806
1807 if (first_member)
1808 {
1809 /* Advertisement-interval reset */
1810 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1811 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1812 else
1813 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1814
1815 /* ebgp-multihop reset */
1816 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1817 group->conf->ttl = 255;
1818
1819 /* local-as reset */
1820 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1821 {
1822 group->conf->change_local_as = 0;
1823 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1824 }
1825 }
paulfee0f4c2004-09-13 05:12:46 +00001826
1827 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1828 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001829 struct listnode *pn;
1830
paulfee0f4c2004-09-13 05:12:46 +00001831 /* If it's not configured as RSERVER_CLIENT in any other address
1832 family, without being member of a peer_group, remove it from
1833 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001834 if (! peer_rsclient_active (peer)
1835 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001836 {
1837 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001839
1840 /* Clear our own rsclient rib for this afi/safi. */
1841 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001842 }
paulfee0f4c2004-09-13 05:12:46 +00001843
Paul Jakmab608d5b2008-07-02 02:12:07 +00001844 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001845
1846 /* Import policy. */
1847 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1848 {
1849 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1850 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1851 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1852 }
1853
1854 /* Export policy. */
1855 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1856 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1859 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1861 }
1862 }
1863
paul718e3742002-12-13 20:15:29 +00001864 peer_group2peer_config_copy (group, peer, afi, safi);
1865
1866 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001867 {
1868 peer->last_reset = PEER_DOWN_RMAP_BIND;
1869 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1870 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1871 }
paul718e3742002-12-13 20:15:29 +00001872 else
1873 BGP_EVENT_ADD (peer, BGP_Stop);
1874
1875 return 0;
1876}
1877
1878int
1879peer_group_unbind (struct bgp *bgp, struct peer *peer,
1880 struct peer_group *group, afi_t afi, safi_t safi)
1881{
1882 if (! peer->af_group[afi][safi])
1883 return 0;
1884
1885 if (group != peer->group)
1886 return BGP_ERR_PEER_GROUP_MISMATCH;
1887
1888 peer->af_group[afi][safi] = 0;
1889 peer->afc[afi][safi] = 0;
1890 peer_af_flag_reset (peer, afi, safi);
1891
paulfee0f4c2004-09-13 05:12:46 +00001892 if (peer->rib[afi][safi])
1893 peer->rib[afi][safi] = NULL;
1894
paul718e3742002-12-13 20:15:29 +00001895 if (! peer_group_active (peer))
1896 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001897 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001898 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001899 listnode_delete (group->peer, peer);
1900 peer->group = NULL;
1901 if (group->conf->as)
1902 {
1903 peer_delete (peer);
1904 return 0;
1905 }
1906 peer_global_config_reset (peer);
1907 }
1908
1909 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001910 {
1911 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1912 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1913 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1914 }
paul718e3742002-12-13 20:15:29 +00001915 else
1916 BGP_EVENT_ADD (peer, BGP_Stop);
1917
1918 return 0;
1919}
1920
1921/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001922static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001923bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001924{
1925 struct bgp *bgp;
1926 afi_t afi;
1927 safi_t safi;
1928
paul200df112005-06-01 11:17:05 +00001929 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1930 return NULL;
1931
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001932 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001933 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001934 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001935
1936 bgp->peer = list_new ();
1937 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1938
1939 bgp->group = list_new ();
1940 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1941
paulfee0f4c2004-09-13 05:12:46 +00001942 bgp->rsclient = list_new ();
1943 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1944
paul718e3742002-12-13 20:15:29 +00001945 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1946 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1947 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001948 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1949 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1950 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001951 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1952 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001953 }
1954
1955 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1956 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1957 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001958 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1959 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001960
1961 bgp->as = *as;
1962
1963 if (name)
1964 bgp->name = strdup (name);
1965
1966 return bgp;
1967}
1968
1969/* Return first entry of BGP. */
1970struct bgp *
paul94f2b392005-06-28 12:44:16 +00001971bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001972{
1973 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001974 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001975 return NULL;
1976}
1977
1978/* Lookup BGP entry. */
1979struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001980bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001981{
1982 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001984
paul1eb8ef22005-04-07 07:30:20 +00001985 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001986 if (bgp->as == as
1987 && ((bgp->name == NULL && name == NULL)
1988 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1989 return bgp;
1990 return NULL;
1991}
1992
1993/* Lookup BGP structure by view name. */
1994struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001995bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001996{
1997 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001998 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001999
paul1eb8ef22005-04-07 07:30:20 +00002000 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002001 if ((bgp->name == NULL && name == NULL)
2002 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2003 return bgp;
2004 return NULL;
2005}
2006
2007/* Called from VTY commands. */
2008int
paulfd79ac92004-10-13 05:06:08 +00002009bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002010{
2011 struct bgp *bgp;
2012
2013 /* Multiple instance check. */
2014 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2015 {
2016 if (name)
2017 bgp = bgp_lookup_by_name (name);
2018 else
2019 bgp = bgp_get_default ();
2020
2021 /* Already exists. */
2022 if (bgp)
2023 {
2024 if (bgp->as != *as)
2025 {
2026 *as = bgp->as;
2027 return BGP_ERR_INSTANCE_MISMATCH;
2028 }
2029 *bgp_val = bgp;
2030 return 0;
2031 }
2032 }
2033 else
2034 {
2035 /* BGP instance name can not be specified for single instance. */
2036 if (name)
2037 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2038
2039 /* Get default BGP structure if exists. */
2040 bgp = bgp_get_default ();
2041
2042 if (bgp)
2043 {
2044 if (bgp->as != *as)
2045 {
2046 *as = bgp->as;
2047 return BGP_ERR_AS_MISMATCH;
2048 }
2049 *bgp_val = bgp;
2050 return 0;
2051 }
2052 }
2053
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002054 bgp = bgp_create (as, name);
2055 bgp_router_id_set(bgp, &router_id_zebra);
2056 *bgp_val = bgp;
2057
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002058 /* Create BGP server socket, if first instance. */
2059 if (list_isempty(bm->bgp))
2060 {
2061 if (bgp_socket (bm->port, bm->address) < 0)
2062 return BGP_ERR_INVALID_VALUE;
2063 }
2064
paul718e3742002-12-13 20:15:29 +00002065 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002066
2067 return 0;
2068}
2069
2070/* Delete BGP instance. */
2071int
2072bgp_delete (struct bgp *bgp)
2073{
2074 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002075 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002076 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002077 struct listnode *next;
2078 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002079 int i;
2080
2081 /* Delete static route. */
2082 bgp_static_delete (bgp);
2083
2084 /* Unset redistribution. */
2085 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2086 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2087 if (i != ZEBRA_ROUTE_BGP)
2088 bgp_redistribute_unset (bgp, afi, i);
2089
paul1eb8ef22005-04-07 07:30:20 +00002090 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2091 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002092
Chris Caputo228da422009-07-18 05:44:03 +00002093 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2094 peer_group_delete (group);
2095
2096 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002097
2098 if (bgp->peer_self) {
2099 peer_delete(bgp->peer_self);
2100 bgp->peer_self = NULL;
2101 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002102
2103 /* Remove visibility via the master list - there may however still be
2104 * routes to be processed still referencing the struct bgp.
2105 */
2106 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002107 if (list_isempty(bm->bgp))
2108 bgp_close ();
2109
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002110 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002111
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002112 return 0;
2113}
2114
2115static void bgp_free (struct bgp *);
2116
2117void
2118bgp_lock (struct bgp *bgp)
2119{
2120 ++bgp->lock;
2121}
2122
2123void
2124bgp_unlock(struct bgp *bgp)
2125{
Chris Caputo228da422009-07-18 05:44:03 +00002126 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002127 if (--bgp->lock == 0)
2128 bgp_free (bgp);
2129}
2130
2131static void
2132bgp_free (struct bgp *bgp)
2133{
2134 afi_t afi;
2135 safi_t safi;
2136
2137 list_delete (bgp->group);
2138 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002139 list_delete (bgp->rsclient);
2140
paul718e3742002-12-13 20:15:29 +00002141 if (bgp->name)
2142 free (bgp->name);
2143
2144 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2145 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2146 {
2147 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002148 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002149 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002150 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002151 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002152 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002153 }
2154 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002155}
2156
2157struct peer *
2158peer_lookup (struct bgp *bgp, union sockunion *su)
2159{
2160 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002161 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002162
Steve Hillfc4dc592009-07-28 17:54:35 +01002163 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002164 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002165 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2166 if (sockunion_same (&peer->su, su)
2167 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2168 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002169 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002170 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002171 {
2172 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002173
Paul Jakma2158ad22009-07-28 18:10:55 +01002174 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2175 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2176 if (sockunion_same (&peer->su, su)
2177 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2178 return peer;
paul718e3742002-12-13 20:15:29 +00002179 }
2180 return NULL;
2181}
2182
2183struct peer *
2184peer_lookup_with_open (union sockunion *su, as_t remote_as,
2185 struct in_addr *remote_id, int *as)
2186{
2187 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002188 struct listnode *node;
2189 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002190 struct bgp *bgp;
2191
Steve Hillfc4dc592009-07-28 17:54:35 +01002192 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002193 return NULL;
2194
Paul Jakma9d878772009-08-05 16:25:16 +01002195 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002196 {
Paul Jakma9d878772009-08-05 16:25:16 +01002197 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2198 {
2199 if (sockunion_same (&peer->su, su)
2200 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2201 {
2202 if (peer->as == remote_as
2203 && peer->remote_id.s_addr == remote_id->s_addr)
2204 return peer;
2205 if (peer->as == remote_as)
2206 *as = 1;
2207 }
2208 }
2209
2210 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2211 {
2212 if (sockunion_same (&peer->su, su)
2213 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2214 {
2215 if (peer->as == remote_as
2216 && peer->remote_id.s_addr == 0)
2217 return peer;
2218 if (peer->as == remote_as)
2219 *as = 1;
2220 }
2221 }
paul718e3742002-12-13 20:15:29 +00002222 }
2223 return NULL;
2224}
2225
2226/* If peer is configured at least one address family return 1. */
2227int
2228peer_active (struct peer *peer)
2229{
2230 if (peer->afc[AFI_IP][SAFI_UNICAST]
2231 || peer->afc[AFI_IP][SAFI_MULTICAST]
2232 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2233 || peer->afc[AFI_IP6][SAFI_UNICAST]
2234 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2235 return 1;
2236 return 0;
2237}
2238
2239/* If peer is negotiated at least one address family return 1. */
2240int
2241peer_active_nego (struct peer *peer)
2242{
2243 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2244 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2245 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2246 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2247 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2248 return 1;
2249 return 0;
2250}
2251
2252/* peer_flag_change_type. */
2253enum peer_change_type
2254{
2255 peer_change_none,
2256 peer_change_reset,
2257 peer_change_reset_in,
2258 peer_change_reset_out,
2259};
2260
paul94f2b392005-06-28 12:44:16 +00002261static void
paul718e3742002-12-13 20:15:29 +00002262peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2263 enum peer_change_type type)
2264{
2265 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2266 return;
2267
2268 if (type == peer_change_reset)
2269 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2270 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2271 else if (type == peer_change_reset_in)
2272 {
2273 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2274 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2275 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2276 else
2277 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2278 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2279 }
2280 else if (type == peer_change_reset_out)
2281 bgp_announce_route (peer, afi, safi);
2282}
2283
2284struct peer_flag_action
2285{
2286 /* Peer's flag. */
2287 u_int32_t flag;
2288
2289 /* This flag can be set for peer-group member. */
2290 u_char not_for_member;
2291
2292 /* Action when the flag is changed. */
2293 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002294
2295 /* Peer down cause */
2296 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002297};
2298
Stephen Hemminger03621952009-07-21 16:27:20 -07002299static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002300 {
2301 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2302 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2303 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2304 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2305 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002306 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002307 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002308 { 0, 0, 0 }
2309 };
2310
Stephen Hemminger03621952009-07-21 16:27:20 -07002311static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002312 {
2313 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2314 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2315 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2316 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2317 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2318 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2319 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2320 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2321 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2322 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2323 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2324 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2325 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002326 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002327 { 0, 0, 0 }
2328 };
2329
2330/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002331static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002332peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002333 struct peer_flag_action *action, u_int32_t flag)
2334{
2335 int i;
2336 int found = 0;
2337 int reset_in = 0;
2338 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002339 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002340
2341 /* Check peer's frag action. */
2342 for (i = 0; i < size; i++)
2343 {
2344 match = &action_list[i];
2345
2346 if (match->flag == 0)
2347 break;
2348
2349 if (match->flag & flag)
2350 {
2351 found = 1;
2352
2353 if (match->type == peer_change_reset_in)
2354 reset_in = 1;
2355 if (match->type == peer_change_reset_out)
2356 reset_out = 1;
2357 if (match->type == peer_change_reset)
2358 {
2359 reset_in = 1;
2360 reset_out = 1;
2361 }
2362 if (match->not_for_member)
2363 action->not_for_member = 1;
2364 }
2365 }
2366
2367 /* Set peer clear type. */
2368 if (reset_in && reset_out)
2369 action->type = peer_change_reset;
2370 else if (reset_in)
2371 action->type = peer_change_reset_in;
2372 else if (reset_out)
2373 action->type = peer_change_reset_out;
2374 else
2375 action->type = peer_change_none;
2376
2377 return found;
2378}
2379
paul94f2b392005-06-28 12:44:16 +00002380static void
paul718e3742002-12-13 20:15:29 +00002381peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2382{
2383 if (flag == PEER_FLAG_SHUTDOWN)
2384 {
2385 if (CHECK_FLAG (peer->flags, flag))
2386 {
hasso93406d82005-02-02 14:40:33 +00002387 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2388 peer_nsf_stop (peer);
2389
hasso0a486e52005-02-01 20:57:17 +00002390 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2391 if (peer->t_pmax_restart)
2392 {
2393 BGP_TIMER_OFF (peer->t_pmax_restart);
2394 if (BGP_DEBUG (events, EVENTS))
2395 zlog_debug ("%s Maximum-prefix restart timer canceled",
2396 peer->host);
2397 }
2398
hasso93406d82005-02-02 14:40:33 +00002399 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2400 peer_nsf_stop (peer);
2401
paul718e3742002-12-13 20:15:29 +00002402 if (peer->status == Established)
2403 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2404 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2405 else
2406 BGP_EVENT_ADD (peer, BGP_Stop);
2407 }
2408 else
2409 {
2410 peer->v_start = BGP_INIT_START_TIMER;
2411 BGP_EVENT_ADD (peer, BGP_Stop);
2412 }
2413 }
2414 else if (peer->status == Established)
2415 {
hassoc9502432005-02-01 22:01:48 +00002416 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2417 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2418 else if (flag == PEER_FLAG_PASSIVE)
2419 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002420 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002421 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002422
hassoc9502432005-02-01 22:01:48 +00002423 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2424 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002425 }
2426 else
2427 BGP_EVENT_ADD (peer, BGP_Stop);
2428}
2429
2430/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002431static int
paul718e3742002-12-13 20:15:29 +00002432peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2433{
2434 int found;
2435 int size;
2436 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002437 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002438 struct peer_flag_action action;
2439
2440 memset (&action, 0, sizeof (struct peer_flag_action));
2441 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2442
2443 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2444
2445 /* No flag action is found. */
2446 if (! found)
2447 return BGP_ERR_INVALID_FLAG;
2448
2449 /* Not for peer-group member. */
2450 if (action.not_for_member && peer_group_active (peer))
2451 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2452
2453 /* When unset the peer-group member's flag we have to check
2454 peer-group configuration. */
2455 if (! set && peer_group_active (peer))
2456 if (CHECK_FLAG (peer->group->conf->flags, flag))
2457 {
2458 if (flag == PEER_FLAG_SHUTDOWN)
2459 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2460 else
2461 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2462 }
2463
2464 /* Flag conflict check. */
2465 if (set
2466 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2467 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2468 return BGP_ERR_PEER_FLAG_CONFLICT;
2469
2470 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2471 {
2472 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2473 return 0;
2474 if (! set && ! CHECK_FLAG (peer->flags, flag))
2475 return 0;
2476 }
2477
2478 if (set)
2479 SET_FLAG (peer->flags, flag);
2480 else
2481 UNSET_FLAG (peer->flags, flag);
2482
2483 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2484 {
2485 if (action.type == peer_change_reset)
2486 peer_flag_modify_action (peer, flag);
2487
2488 return 0;
2489 }
2490
2491 /* peer-group member updates. */
2492 group = peer->group;
2493
paul1eb8ef22005-04-07 07:30:20 +00002494 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002495 {
2496 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2497 continue;
2498
2499 if (! set && ! CHECK_FLAG (peer->flags, flag))
2500 continue;
2501
2502 if (set)
2503 SET_FLAG (peer->flags, flag);
2504 else
2505 UNSET_FLAG (peer->flags, flag);
2506
2507 if (action.type == peer_change_reset)
2508 peer_flag_modify_action (peer, flag);
2509 }
2510 return 0;
2511}
2512
2513int
2514peer_flag_set (struct peer *peer, u_int32_t flag)
2515{
2516 return peer_flag_modify (peer, flag, 1);
2517}
2518
2519int
2520peer_flag_unset (struct peer *peer, u_int32_t flag)
2521{
2522 return peer_flag_modify (peer, flag, 0);
2523}
2524
paul94f2b392005-06-28 12:44:16 +00002525static int
paul718e3742002-12-13 20:15:29 +00002526peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2527{
2528 if (peer->af_group[afi][safi])
2529 return 1;
2530 return 0;
2531}
2532
paul94f2b392005-06-28 12:44:16 +00002533static int
paul718e3742002-12-13 20:15:29 +00002534peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2535 int set)
2536{
2537 int found;
2538 int size;
paul1eb8ef22005-04-07 07:30:20 +00002539 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002540 struct peer_group *group;
2541 struct peer_flag_action action;
2542
2543 memset (&action, 0, sizeof (struct peer_flag_action));
2544 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2545
2546 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2547
2548 /* No flag action is found. */
2549 if (! found)
2550 return BGP_ERR_INVALID_FLAG;
2551
2552 /* Adress family must be activated. */
2553 if (! peer->afc[afi][safi])
2554 return BGP_ERR_PEER_INACTIVE;
2555
2556 /* Not for peer-group member. */
2557 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2558 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2559
2560 /* Spcecial check for reflector client. */
2561 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2562 && peer_sort (peer) != BGP_PEER_IBGP)
2563 return BGP_ERR_NOT_INTERNAL_PEER;
2564
2565 /* Spcecial check for remove-private-AS. */
2566 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2567 && peer_sort (peer) == BGP_PEER_IBGP)
2568 return BGP_ERR_REMOVE_PRIVATE_AS;
2569
2570 /* When unset the peer-group member's flag we have to check
2571 peer-group configuration. */
2572 if (! set && peer->af_group[afi][safi])
2573 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2574 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2575
2576 /* When current flag configuration is same as requested one. */
2577 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2578 {
2579 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2580 return 0;
2581 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2582 return 0;
2583 }
2584
2585 if (set)
2586 SET_FLAG (peer->af_flags[afi][safi], flag);
2587 else
2588 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2589
2590 /* Execute action when peer is established. */
2591 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2592 && peer->status == Established)
2593 {
2594 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2595 bgp_clear_adj_in (peer, afi, safi);
2596 else
hassoe0701b72004-05-20 09:19:34 +00002597 {
2598 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2599 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2600 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2601 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2602 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2603 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2604 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2605 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2606
2607 peer_change_action (peer, afi, safi, action.type);
2608 }
2609
paul718e3742002-12-13 20:15:29 +00002610 }
2611
2612 /* Peer group member updates. */
2613 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2614 {
2615 group = peer->group;
2616
paul1eb8ef22005-04-07 07:30:20 +00002617 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002618 {
2619 if (! peer->af_group[afi][safi])
2620 continue;
2621
2622 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2623 continue;
2624
2625 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2626 continue;
2627
2628 if (set)
2629 SET_FLAG (peer->af_flags[afi][safi], flag);
2630 else
2631 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2632
2633 if (peer->status == Established)
2634 {
2635 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2636 bgp_clear_adj_in (peer, afi, safi);
2637 else
hassoe0701b72004-05-20 09:19:34 +00002638 {
2639 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2640 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2641 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2642 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2643 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2644 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2645 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2646 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2647
2648 peer_change_action (peer, afi, safi, action.type);
2649 }
paul718e3742002-12-13 20:15:29 +00002650 }
2651 }
2652 }
2653 return 0;
2654}
2655
2656int
2657peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2658{
2659 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2660}
2661
2662int
2663peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2664{
2665 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2666}
2667
2668/* EBGP multihop configuration. */
2669int
2670peer_ebgp_multihop_set (struct peer *peer, int ttl)
2671{
2672 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002673 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002674 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002675
2676 if (peer_sort (peer) == BGP_PEER_IBGP)
2677 return 0;
2678
Nick Hilliardfa411a22011-03-23 15:33:17 +00002679 /* see comment in peer_ttl_security_hops_set() */
2680 if (ttl != MAXTTL)
2681 {
2682 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2683 {
2684 group = peer->group;
2685 if (group->conf->gtsm_hops != 0)
2686 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2687
2688 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2689 {
2690 if (peer_sort (peer1) == BGP_PEER_IBGP)
2691 continue;
2692
2693 if (peer1->gtsm_hops != 0)
2694 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2695 }
2696 }
2697 else
2698 {
2699 if (peer->gtsm_hops != 0)
2700 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2701 }
2702 }
2703
paul718e3742002-12-13 20:15:29 +00002704 peer->ttl = ttl;
2705
2706 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2707 {
pauleb821182004-05-01 08:44:08 +00002708 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2709 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002710 }
2711 else
2712 {
2713 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002714 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002715 {
2716 if (peer_sort (peer) == BGP_PEER_IBGP)
2717 continue;
paul718e3742002-12-13 20:15:29 +00002718
pauleb821182004-05-01 08:44:08 +00002719 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002720
pauleb821182004-05-01 08:44:08 +00002721 if (peer->fd >= 0)
2722 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2723 }
paul718e3742002-12-13 20:15:29 +00002724 }
2725 return 0;
2726}
2727
2728int
2729peer_ebgp_multihop_unset (struct peer *peer)
2730{
2731 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002732 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002733
2734 if (peer_sort (peer) == BGP_PEER_IBGP)
2735 return 0;
2736
Nick Hilliardfa411a22011-03-23 15:33:17 +00002737 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2738 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2739
paul718e3742002-12-13 20:15:29 +00002740 if (peer_group_active (peer))
2741 peer->ttl = peer->group->conf->ttl;
2742 else
2743 peer->ttl = 1;
2744
2745 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2746 {
pauleb821182004-05-01 08:44:08 +00002747 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2748 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002749 }
2750 else
2751 {
2752 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002753 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002754 {
2755 if (peer_sort (peer) == BGP_PEER_IBGP)
2756 continue;
paul718e3742002-12-13 20:15:29 +00002757
pauleb821182004-05-01 08:44:08 +00002758 peer->ttl = 1;
2759
2760 if (peer->fd >= 0)
2761 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2762 }
paul718e3742002-12-13 20:15:29 +00002763 }
2764 return 0;
2765}
2766
2767/* Neighbor description. */
2768int
2769peer_description_set (struct peer *peer, char *desc)
2770{
2771 if (peer->desc)
2772 XFREE (MTYPE_PEER_DESC, peer->desc);
2773
2774 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2775
2776 return 0;
2777}
2778
2779int
2780peer_description_unset (struct peer *peer)
2781{
2782 if (peer->desc)
2783 XFREE (MTYPE_PEER_DESC, peer->desc);
2784
2785 peer->desc = NULL;
2786
2787 return 0;
2788}
2789
2790/* Neighbor update-source. */
2791int
paulfd79ac92004-10-13 05:06:08 +00002792peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002793{
2794 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002795 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002796
2797 if (peer->update_if)
2798 {
2799 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2800 && strcmp (peer->update_if, ifname) == 0)
2801 return 0;
2802
2803 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2804 peer->update_if = NULL;
2805 }
2806
2807 if (peer->update_source)
2808 {
2809 sockunion_free (peer->update_source);
2810 peer->update_source = NULL;
2811 }
2812
2813 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2814
2815 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2816 {
2817 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002818 {
2819 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2820 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2821 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2822 }
paul718e3742002-12-13 20:15:29 +00002823 else
2824 BGP_EVENT_ADD (peer, BGP_Stop);
2825 return 0;
2826 }
2827
2828 /* peer-group member updates. */
2829 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002830 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002831 {
2832 if (peer->update_if)
2833 {
2834 if (strcmp (peer->update_if, ifname) == 0)
2835 continue;
2836
2837 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2838 peer->update_if = NULL;
2839 }
2840
2841 if (peer->update_source)
2842 {
2843 sockunion_free (peer->update_source);
2844 peer->update_source = NULL;
2845 }
2846
2847 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2848
2849 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002850 {
2851 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2852 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2853 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2854 }
paul718e3742002-12-13 20:15:29 +00002855 else
2856 BGP_EVENT_ADD (peer, BGP_Stop);
2857 }
2858 return 0;
2859}
2860
2861int
2862peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2863{
2864 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002865 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002866
2867 if (peer->update_source)
2868 {
2869 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2870 && sockunion_cmp (peer->update_source, su) == 0)
2871 return 0;
2872 sockunion_free (peer->update_source);
2873 peer->update_source = NULL;
2874 }
2875
2876 if (peer->update_if)
2877 {
2878 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2879 peer->update_if = NULL;
2880 }
2881
2882 peer->update_source = sockunion_dup (su);
2883
2884 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2885 {
2886 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002887 {
2888 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2889 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2890 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2891 }
paul718e3742002-12-13 20:15:29 +00002892 else
2893 BGP_EVENT_ADD (peer, BGP_Stop);
2894 return 0;
2895 }
2896
2897 /* peer-group member updates. */
2898 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002899 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002900 {
2901 if (peer->update_source)
2902 {
2903 if (sockunion_cmp (peer->update_source, su) == 0)
2904 continue;
2905 sockunion_free (peer->update_source);
2906 peer->update_source = NULL;
2907 }
2908
2909 if (peer->update_if)
2910 {
2911 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2912 peer->update_if = NULL;
2913 }
2914
2915 peer->update_source = sockunion_dup (su);
2916
2917 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002918 {
2919 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2920 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2921 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2922 }
paul718e3742002-12-13 20:15:29 +00002923 else
2924 BGP_EVENT_ADD (peer, BGP_Stop);
2925 }
2926 return 0;
2927}
2928
2929int
2930peer_update_source_unset (struct peer *peer)
2931{
2932 union sockunion *su;
2933 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002934 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002935
2936 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2937 && ! peer->update_source
2938 && ! peer->update_if)
2939 return 0;
2940
2941 if (peer->update_source)
2942 {
2943 sockunion_free (peer->update_source);
2944 peer->update_source = NULL;
2945 }
2946 if (peer->update_if)
2947 {
2948 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2949 peer->update_if = NULL;
2950 }
2951
2952 if (peer_group_active (peer))
2953 {
2954 group = peer->group;
2955
2956 if (group->conf->update_source)
2957 {
2958 su = sockunion_dup (group->conf->update_source);
2959 peer->update_source = su;
2960 }
2961 else if (group->conf->update_if)
2962 peer->update_if =
2963 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2964 }
2965
2966 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2967 {
2968 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002969 {
2970 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2971 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2972 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2973 }
paul718e3742002-12-13 20:15:29 +00002974 else
2975 BGP_EVENT_ADD (peer, BGP_Stop);
2976 return 0;
2977 }
2978
2979 /* peer-group member updates. */
2980 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002981 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002982 {
2983 if (! peer->update_source && ! peer->update_if)
2984 continue;
2985
2986 if (peer->update_source)
2987 {
2988 sockunion_free (peer->update_source);
2989 peer->update_source = NULL;
2990 }
2991
2992 if (peer->update_if)
2993 {
2994 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2995 peer->update_if = NULL;
2996 }
2997
2998 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002999 {
3000 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3001 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3002 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3003 }
paul718e3742002-12-13 20:15:29 +00003004 else
3005 BGP_EVENT_ADD (peer, BGP_Stop);
3006 }
3007 return 0;
3008}
3009
3010int
3011peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003012 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003013{
3014 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003015 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003016
3017 /* Adress family must be activated. */
3018 if (! peer->afc[afi][safi])
3019 return BGP_ERR_PEER_INACTIVE;
3020
3021 /* Default originate can't be used for peer group memeber. */
3022 if (peer_is_group_member (peer, afi, safi))
3023 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3024
3025 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3026 || (rmap && ! peer->default_rmap[afi][safi].name)
3027 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3028 {
3029 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3030
3031 if (rmap)
3032 {
3033 if (peer->default_rmap[afi][safi].name)
3034 free (peer->default_rmap[afi][safi].name);
3035 peer->default_rmap[afi][safi].name = strdup (rmap);
3036 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3037 }
3038 }
3039
3040 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3041 {
3042 if (peer->status == Established && peer->afc_nego[afi][safi])
3043 bgp_default_originate (peer, afi, safi, 0);
3044 return 0;
3045 }
3046
3047 /* peer-group member updates. */
3048 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003049 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003050 {
3051 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3052
3053 if (rmap)
3054 {
3055 if (peer->default_rmap[afi][safi].name)
3056 free (peer->default_rmap[afi][safi].name);
3057 peer->default_rmap[afi][safi].name = strdup (rmap);
3058 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3059 }
3060
3061 if (peer->status == Established && peer->afc_nego[afi][safi])
3062 bgp_default_originate (peer, afi, safi, 0);
3063 }
3064 return 0;
3065}
3066
3067int
3068peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3069{
3070 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003071 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003072
3073 /* Adress family must be activated. */
3074 if (! peer->afc[afi][safi])
3075 return BGP_ERR_PEER_INACTIVE;
3076
3077 /* Default originate can't be used for peer group memeber. */
3078 if (peer_is_group_member (peer, afi, safi))
3079 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3080
3081 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3082 {
3083 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3084
3085 if (peer->default_rmap[afi][safi].name)
3086 free (peer->default_rmap[afi][safi].name);
3087 peer->default_rmap[afi][safi].name = NULL;
3088 peer->default_rmap[afi][safi].map = NULL;
3089 }
3090
3091 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3092 {
3093 if (peer->status == Established && peer->afc_nego[afi][safi])
3094 bgp_default_originate (peer, afi, safi, 1);
3095 return 0;
3096 }
3097
3098 /* peer-group member updates. */
3099 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003100 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003101 {
3102 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3103
3104 if (peer->default_rmap[afi][safi].name)
3105 free (peer->default_rmap[afi][safi].name);
3106 peer->default_rmap[afi][safi].name = NULL;
3107 peer->default_rmap[afi][safi].map = NULL;
3108
3109 if (peer->status == Established && peer->afc_nego[afi][safi])
3110 bgp_default_originate (peer, afi, safi, 1);
3111 }
3112 return 0;
3113}
3114
3115int
3116peer_port_set (struct peer *peer, u_int16_t port)
3117{
3118 peer->port = port;
3119 return 0;
3120}
3121
3122int
3123peer_port_unset (struct peer *peer)
3124{
3125 peer->port = BGP_PORT_DEFAULT;
3126 return 0;
3127}
3128
3129/* neighbor weight. */
3130int
3131peer_weight_set (struct peer *peer, u_int16_t weight)
3132{
3133 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003134 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003135
3136 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3137 peer->weight = weight;
3138
3139 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3140 return 0;
3141
3142 /* peer-group member updates. */
3143 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003144 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003145 {
3146 peer->weight = group->conf->weight;
3147 }
3148 return 0;
3149}
3150
3151int
3152peer_weight_unset (struct peer *peer)
3153{
3154 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003156
3157 /* Set default weight. */
3158 if (peer_group_active (peer))
3159 peer->weight = peer->group->conf->weight;
3160 else
3161 peer->weight = 0;
3162
3163 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3164
3165 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3166 return 0;
3167
3168 /* peer-group member updates. */
3169 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003170 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003171 {
3172 peer->weight = 0;
3173 }
3174 return 0;
3175}
3176
3177int
3178peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3179{
3180 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003181 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003182
3183 /* Not for peer group memeber. */
3184 if (peer_group_active (peer))
3185 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3186
3187 /* keepalive value check. */
3188 if (keepalive > 65535)
3189 return BGP_ERR_INVALID_VALUE;
3190
3191 /* Holdtime value check. */
3192 if (holdtime > 65535)
3193 return BGP_ERR_INVALID_VALUE;
3194
3195 /* Holdtime value must be either 0 or greater than 3. */
3196 if (holdtime < 3 && holdtime != 0)
3197 return BGP_ERR_INVALID_VALUE;
3198
3199 /* Set value to the configuration. */
3200 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3201 peer->holdtime = holdtime;
3202 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3203
3204 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3205 return 0;
3206
3207 /* peer-group member updates. */
3208 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003209 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003210 {
3211 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3212 peer->holdtime = group->conf->holdtime;
3213 peer->keepalive = group->conf->keepalive;
3214 }
3215 return 0;
3216}
3217
3218int
3219peer_timers_unset (struct peer *peer)
3220{
3221 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003223
3224 if (peer_group_active (peer))
3225 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3226
3227 /* Clear configuration. */
3228 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3229 peer->keepalive = 0;
3230 peer->holdtime = 0;
3231
3232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3233 return 0;
3234
3235 /* peer-group member updates. */
3236 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003237 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003238 {
3239 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3240 peer->holdtime = 0;
3241 peer->keepalive = 0;
3242 }
3243
3244 return 0;
3245}
3246
3247int
3248peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3249{
3250 if (peer_group_active (peer))
3251 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3252
3253 if (connect > 65535)
3254 return BGP_ERR_INVALID_VALUE;
3255
3256 /* Set value to the configuration. */
3257 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3258 peer->connect = connect;
3259
3260 /* Set value to timer setting. */
3261 peer->v_connect = connect;
3262
3263 return 0;
3264}
3265
3266int
3267peer_timers_connect_unset (struct peer *peer)
3268{
3269 if (peer_group_active (peer))
3270 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3271
3272 /* Clear configuration. */
3273 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3274 peer->connect = 0;
3275
3276 /* Set timer setting to default value. */
3277 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3278
3279 return 0;
3280}
3281
3282int
3283peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3284{
3285 if (peer_group_active (peer))
3286 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3287
3288 if (routeadv > 600)
3289 return BGP_ERR_INVALID_VALUE;
3290
3291 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3292 peer->routeadv = routeadv;
3293 peer->v_routeadv = routeadv;
3294
3295 return 0;
3296}
3297
3298int
3299peer_advertise_interval_unset (struct peer *peer)
3300{
3301 if (peer_group_active (peer))
3302 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3303
3304 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3305 peer->routeadv = 0;
3306
3307 if (peer_sort (peer) == BGP_PEER_IBGP)
3308 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3309 else
3310 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3311
3312 return 0;
3313}
3314
paul718e3742002-12-13 20:15:29 +00003315/* neighbor interface */
3316int
paulfd79ac92004-10-13 05:06:08 +00003317peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003318{
3319 if (peer->ifname)
3320 free (peer->ifname);
3321 peer->ifname = strdup (str);
3322
3323 return 0;
3324}
3325
3326int
3327peer_interface_unset (struct peer *peer)
3328{
3329 if (peer->ifname)
3330 free (peer->ifname);
3331 peer->ifname = NULL;
3332
3333 return 0;
3334}
3335
3336/* Allow-as in. */
3337int
3338peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3339{
3340 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003341 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003342
3343 if (allow_num < 1 || allow_num > 10)
3344 return BGP_ERR_INVALID_VALUE;
3345
3346 if (peer->allowas_in[afi][safi] != allow_num)
3347 {
3348 peer->allowas_in[afi][safi] = allow_num;
3349 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3350 peer_change_action (peer, afi, safi, peer_change_reset_in);
3351 }
3352
3353 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3354 return 0;
3355
3356 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003357 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003358 {
3359 if (peer->allowas_in[afi][safi] != allow_num)
3360 {
3361 peer->allowas_in[afi][safi] = allow_num;
3362 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3363 peer_change_action (peer, afi, safi, peer_change_reset_in);
3364 }
3365
3366 }
3367 return 0;
3368}
3369
3370int
3371peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3372{
3373 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003374 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003375
3376 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3377 {
3378 peer->allowas_in[afi][safi] = 0;
3379 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3380 }
3381
3382 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3383 return 0;
3384
3385 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003386 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003387 {
3388 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3389 {
3390 peer->allowas_in[afi][safi] = 0;
3391 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3392 }
3393 }
3394 return 0;
3395}
3396
3397int
3398peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3399{
3400 struct bgp *bgp = peer->bgp;
3401 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003402 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003403
3404 if (peer_sort (peer) != BGP_PEER_EBGP
3405 && peer_sort (peer) != BGP_PEER_INTERNAL)
3406 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3407
3408 if (bgp->as == as)
3409 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3410
3411 if (peer_group_active (peer))
3412 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3413
3414 if (peer->change_local_as == as &&
3415 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3416 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3417 return 0;
3418
3419 peer->change_local_as = as;
3420 if (no_prepend)
3421 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3422 else
3423 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3424
3425 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3426 {
3427 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003428 {
3429 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3430 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3431 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3432 }
paul718e3742002-12-13 20:15:29 +00003433 else
3434 BGP_EVENT_ADD (peer, BGP_Stop);
3435
3436 return 0;
3437 }
3438
3439 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003440 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003441 {
3442 peer->change_local_as = as;
3443 if (no_prepend)
3444 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3445 else
3446 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3447
3448 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003449 {
3450 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3451 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3452 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3453 }
paul718e3742002-12-13 20:15:29 +00003454 else
3455 BGP_EVENT_ADD (peer, BGP_Stop);
3456 }
3457
3458 return 0;
3459}
3460
3461int
3462peer_local_as_unset (struct peer *peer)
3463{
3464 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003465 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003466
3467 if (peer_group_active (peer))
3468 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3469
3470 if (! peer->change_local_as)
3471 return 0;
3472
3473 peer->change_local_as = 0;
3474 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3475
3476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3477 {
3478 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003479 {
3480 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3481 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3482 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3483 }
paul718e3742002-12-13 20:15:29 +00003484 else
3485 BGP_EVENT_ADD (peer, BGP_Stop);
3486
3487 return 0;
3488 }
3489
3490 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003491 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003492 {
3493 peer->change_local_as = 0;
3494 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3495
3496 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003497 {
3498 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3499 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3500 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3501 }
paul718e3742002-12-13 20:15:29 +00003502 else
3503 BGP_EVENT_ADD (peer, BGP_Stop);
3504 }
3505 return 0;
3506}
3507
Paul Jakma0df7c912008-07-21 21:02:49 +00003508/* Set password for authenticating with the peer. */
3509int
3510peer_password_set (struct peer *peer, const char *password)
3511{
3512 struct listnode *nn, *nnode;
3513 int len = password ? strlen(password) : 0;
3514 int ret = BGP_SUCCESS;
3515
3516 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3517 return BGP_ERR_INVALID_VALUE;
3518
3519 if (peer->password && strcmp (peer->password, password) == 0
3520 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3521 return 0;
3522
3523 if (peer->password)
3524 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3525
3526 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3527
3528 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3529 {
3530 if (peer->status == Established)
3531 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3532 else
3533 BGP_EVENT_ADD (peer, BGP_Stop);
3534
3535 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3536 }
3537
3538 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3539 {
3540 if (peer->password && strcmp (peer->password, password) == 0)
3541 continue;
3542
3543 if (peer->password)
3544 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3545
3546 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3547
3548 if (peer->status == Established)
3549 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3550 else
3551 BGP_EVENT_ADD (peer, BGP_Stop);
3552
3553 if (bgp_md5_set (peer) < 0)
3554 ret = BGP_ERR_TCPSIG_FAILED;
3555 }
3556
3557 return ret;
3558}
3559
3560int
3561peer_password_unset (struct peer *peer)
3562{
3563 struct listnode *nn, *nnode;
3564
3565 if (!peer->password
3566 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3567 return 0;
3568
3569 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3570 {
3571 if (peer_group_active (peer)
3572 && peer->group->conf->password
3573 && strcmp (peer->group->conf->password, peer->password) == 0)
3574 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3575
3576 if (peer->status == Established)
3577 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3578 else
3579 BGP_EVENT_ADD (peer, BGP_Stop);
3580
3581 if (peer->password)
3582 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3583
3584 peer->password = NULL;
3585
3586 bgp_md5_set (peer);
3587
3588 return 0;
3589 }
3590
3591 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3592 peer->password = NULL;
3593
3594 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3595 {
3596 if (!peer->password)
3597 continue;
3598
3599 if (peer->status == Established)
3600 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3601 else
3602 BGP_EVENT_ADD (peer, BGP_Stop);
3603
3604 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3605 peer->password = NULL;
3606
3607 bgp_md5_set (peer);
3608 }
3609
3610 return 0;
3611}
3612
paul718e3742002-12-13 20:15:29 +00003613/* Set distribute list to the peer. */
3614int
3615peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003616 const char *name)
paul718e3742002-12-13 20:15:29 +00003617{
3618 struct bgp_filter *filter;
3619 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003620 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003621
3622 if (! peer->afc[afi][safi])
3623 return BGP_ERR_PEER_INACTIVE;
3624
3625 if (direct != FILTER_IN && direct != FILTER_OUT)
3626 return BGP_ERR_INVALID_VALUE;
3627
3628 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3629 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3630
3631 filter = &peer->filter[afi][safi];
3632
3633 if (filter->plist[direct].name)
3634 return BGP_ERR_PEER_FILTER_CONFLICT;
3635
3636 if (filter->dlist[direct].name)
3637 free (filter->dlist[direct].name);
3638 filter->dlist[direct].name = strdup (name);
3639 filter->dlist[direct].alist = access_list_lookup (afi, name);
3640
3641 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3642 return 0;
3643
3644 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003645 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003646 {
3647 filter = &peer->filter[afi][safi];
3648
3649 if (! peer->af_group[afi][safi])
3650 continue;
3651
3652 if (filter->dlist[direct].name)
3653 free (filter->dlist[direct].name);
3654 filter->dlist[direct].name = strdup (name);
3655 filter->dlist[direct].alist = access_list_lookup (afi, name);
3656 }
3657
3658 return 0;
3659}
3660
3661int
3662peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3663{
3664 struct bgp_filter *filter;
3665 struct bgp_filter *gfilter;
3666 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003667 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003668
3669 if (! peer->afc[afi][safi])
3670 return BGP_ERR_PEER_INACTIVE;
3671
3672 if (direct != FILTER_IN && direct != FILTER_OUT)
3673 return BGP_ERR_INVALID_VALUE;
3674
3675 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3676 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3677
3678 filter = &peer->filter[afi][safi];
3679
3680 /* apply peer-group filter */
3681 if (peer->af_group[afi][safi])
3682 {
3683 gfilter = &peer->group->conf->filter[afi][safi];
3684
3685 if (gfilter->dlist[direct].name)
3686 {
3687 if (filter->dlist[direct].name)
3688 free (filter->dlist[direct].name);
3689 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3690 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3691 return 0;
3692 }
3693 }
3694
3695 if (filter->dlist[direct].name)
3696 free (filter->dlist[direct].name);
3697 filter->dlist[direct].name = NULL;
3698 filter->dlist[direct].alist = NULL;
3699
3700 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3701 return 0;
3702
3703 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003704 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003705 {
3706 filter = &peer->filter[afi][safi];
3707
3708 if (! peer->af_group[afi][safi])
3709 continue;
3710
3711 if (filter->dlist[direct].name)
3712 free (filter->dlist[direct].name);
3713 filter->dlist[direct].name = NULL;
3714 filter->dlist[direct].alist = NULL;
3715 }
3716
3717 return 0;
3718}
3719
3720/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003721static void
paul718e3742002-12-13 20:15:29 +00003722peer_distribute_update (struct access_list *access)
3723{
3724 afi_t afi;
3725 safi_t safi;
3726 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003727 struct listnode *mnode, *mnnode;
3728 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003729 struct bgp *bgp;
3730 struct peer *peer;
3731 struct peer_group *group;
3732 struct bgp_filter *filter;
3733
paul1eb8ef22005-04-07 07:30:20 +00003734 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003735 {
paul1eb8ef22005-04-07 07:30:20 +00003736 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003737 {
3738 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3739 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3740 {
3741 filter = &peer->filter[afi][safi];
3742
3743 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3744 {
3745 if (filter->dlist[direct].name)
3746 filter->dlist[direct].alist =
3747 access_list_lookup (afi, filter->dlist[direct].name);
3748 else
3749 filter->dlist[direct].alist = NULL;
3750 }
3751 }
3752 }
paul1eb8ef22005-04-07 07:30:20 +00003753 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003754 {
3755 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3756 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3757 {
3758 filter = &group->conf->filter[afi][safi];
3759
3760 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3761 {
3762 if (filter->dlist[direct].name)
3763 filter->dlist[direct].alist =
3764 access_list_lookup (afi, filter->dlist[direct].name);
3765 else
3766 filter->dlist[direct].alist = NULL;
3767 }
3768 }
3769 }
3770 }
3771}
3772
3773/* Set prefix list to the peer. */
3774int
3775peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003776 const char *name)
paul718e3742002-12-13 20:15:29 +00003777{
3778 struct bgp_filter *filter;
3779 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003780 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003781
3782 if (! peer->afc[afi][safi])
3783 return BGP_ERR_PEER_INACTIVE;
3784
3785 if (direct != FILTER_IN && direct != FILTER_OUT)
3786 return BGP_ERR_INVALID_VALUE;
3787
3788 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3789 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3790
3791 filter = &peer->filter[afi][safi];
3792
3793 if (filter->dlist[direct].name)
3794 return BGP_ERR_PEER_FILTER_CONFLICT;
3795
3796 if (filter->plist[direct].name)
3797 free (filter->plist[direct].name);
3798 filter->plist[direct].name = strdup (name);
3799 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3800
3801 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3802 return 0;
3803
3804 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003805 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003806 {
3807 filter = &peer->filter[afi][safi];
3808
3809 if (! peer->af_group[afi][safi])
3810 continue;
3811
3812 if (filter->plist[direct].name)
3813 free (filter->plist[direct].name);
3814 filter->plist[direct].name = strdup (name);
3815 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3816 }
3817 return 0;
3818}
3819
3820int
3821peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3822{
3823 struct bgp_filter *filter;
3824 struct bgp_filter *gfilter;
3825 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003826 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003827
3828 if (! peer->afc[afi][safi])
3829 return BGP_ERR_PEER_INACTIVE;
3830
3831 if (direct != FILTER_IN && direct != FILTER_OUT)
3832 return BGP_ERR_INVALID_VALUE;
3833
3834 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3835 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3836
3837 filter = &peer->filter[afi][safi];
3838
3839 /* apply peer-group filter */
3840 if (peer->af_group[afi][safi])
3841 {
3842 gfilter = &peer->group->conf->filter[afi][safi];
3843
3844 if (gfilter->plist[direct].name)
3845 {
3846 if (filter->plist[direct].name)
3847 free (filter->plist[direct].name);
3848 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3849 filter->plist[direct].plist = gfilter->plist[direct].plist;
3850 return 0;
3851 }
3852 }
3853
3854 if (filter->plist[direct].name)
3855 free (filter->plist[direct].name);
3856 filter->plist[direct].name = NULL;
3857 filter->plist[direct].plist = NULL;
3858
3859 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3860 return 0;
3861
3862 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003863 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003864 {
3865 filter = &peer->filter[afi][safi];
3866
3867 if (! peer->af_group[afi][safi])
3868 continue;
3869
3870 if (filter->plist[direct].name)
3871 free (filter->plist[direct].name);
3872 filter->plist[direct].name = NULL;
3873 filter->plist[direct].plist = NULL;
3874 }
3875
3876 return 0;
3877}
3878
3879/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003880static void
paul718e3742002-12-13 20:15:29 +00003881peer_prefix_list_update (struct prefix_list *plist)
3882{
paul1eb8ef22005-04-07 07:30:20 +00003883 struct listnode *mnode, *mnnode;
3884 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003885 struct bgp *bgp;
3886 struct peer *peer;
3887 struct peer_group *group;
3888 struct bgp_filter *filter;
3889 afi_t afi;
3890 safi_t safi;
3891 int direct;
3892
paul1eb8ef22005-04-07 07:30:20 +00003893 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003894 {
paul1eb8ef22005-04-07 07:30:20 +00003895 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003896 {
3897 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3898 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3899 {
3900 filter = &peer->filter[afi][safi];
3901
3902 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3903 {
3904 if (filter->plist[direct].name)
3905 filter->plist[direct].plist =
3906 prefix_list_lookup (afi, filter->plist[direct].name);
3907 else
3908 filter->plist[direct].plist = NULL;
3909 }
3910 }
3911 }
paul1eb8ef22005-04-07 07:30:20 +00003912 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003913 {
3914 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3915 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3916 {
3917 filter = &group->conf->filter[afi][safi];
3918
3919 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3920 {
3921 if (filter->plist[direct].name)
3922 filter->plist[direct].plist =
3923 prefix_list_lookup (afi, filter->plist[direct].name);
3924 else
3925 filter->plist[direct].plist = NULL;
3926 }
3927 }
3928 }
3929 }
3930}
3931
3932int
3933peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003934 const char *name)
paul718e3742002-12-13 20:15:29 +00003935{
3936 struct bgp_filter *filter;
3937 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003938 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003939
3940 if (! peer->afc[afi][safi])
3941 return BGP_ERR_PEER_INACTIVE;
3942
3943 if (direct != FILTER_IN && direct != FILTER_OUT)
3944 return BGP_ERR_INVALID_VALUE;
3945
3946 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3947 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3948
3949 filter = &peer->filter[afi][safi];
3950
3951 if (filter->aslist[direct].name)
3952 free (filter->aslist[direct].name);
3953 filter->aslist[direct].name = strdup (name);
3954 filter->aslist[direct].aslist = as_list_lookup (name);
3955
3956 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3957 return 0;
3958
3959 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003960 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003961 {
3962 filter = &peer->filter[afi][safi];
3963
3964 if (! peer->af_group[afi][safi])
3965 continue;
3966
3967 if (filter->aslist[direct].name)
3968 free (filter->aslist[direct].name);
3969 filter->aslist[direct].name = strdup (name);
3970 filter->aslist[direct].aslist = as_list_lookup (name);
3971 }
3972 return 0;
3973}
3974
3975int
3976peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3977{
3978 struct bgp_filter *filter;
3979 struct bgp_filter *gfilter;
3980 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003981 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003982
3983 if (! peer->afc[afi][safi])
3984 return BGP_ERR_PEER_INACTIVE;
3985
hassob5f29602005-05-25 21:00:28 +00003986 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003987 return BGP_ERR_INVALID_VALUE;
3988
hassob5f29602005-05-25 21:00:28 +00003989 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003990 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3991
3992 filter = &peer->filter[afi][safi];
3993
3994 /* apply peer-group filter */
3995 if (peer->af_group[afi][safi])
3996 {
3997 gfilter = &peer->group->conf->filter[afi][safi];
3998
3999 if (gfilter->aslist[direct].name)
4000 {
4001 if (filter->aslist[direct].name)
4002 free (filter->aslist[direct].name);
4003 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4004 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4005 return 0;
4006 }
4007 }
4008
4009 if (filter->aslist[direct].name)
4010 free (filter->aslist[direct].name);
4011 filter->aslist[direct].name = NULL;
4012 filter->aslist[direct].aslist = NULL;
4013
4014 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4015 return 0;
4016
4017 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004018 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004019 {
4020 filter = &peer->filter[afi][safi];
4021
4022 if (! peer->af_group[afi][safi])
4023 continue;
4024
4025 if (filter->aslist[direct].name)
4026 free (filter->aslist[direct].name);
4027 filter->aslist[direct].name = NULL;
4028 filter->aslist[direct].aslist = NULL;
4029 }
4030
4031 return 0;
4032}
4033
paul94f2b392005-06-28 12:44:16 +00004034static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004035peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004036{
4037 afi_t afi;
4038 safi_t safi;
4039 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004040 struct listnode *mnode, *mnnode;
4041 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004042 struct bgp *bgp;
4043 struct peer *peer;
4044 struct peer_group *group;
4045 struct bgp_filter *filter;
4046
paul1eb8ef22005-04-07 07:30:20 +00004047 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004048 {
paul1eb8ef22005-04-07 07:30:20 +00004049 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004050 {
4051 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4052 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4053 {
4054 filter = &peer->filter[afi][safi];
4055
4056 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4057 {
4058 if (filter->aslist[direct].name)
4059 filter->aslist[direct].aslist =
4060 as_list_lookup (filter->aslist[direct].name);
4061 else
4062 filter->aslist[direct].aslist = NULL;
4063 }
4064 }
4065 }
paul1eb8ef22005-04-07 07:30:20 +00004066 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004067 {
4068 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4069 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4070 {
4071 filter = &group->conf->filter[afi][safi];
4072
4073 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4074 {
4075 if (filter->aslist[direct].name)
4076 filter->aslist[direct].aslist =
4077 as_list_lookup (filter->aslist[direct].name);
4078 else
4079 filter->aslist[direct].aslist = NULL;
4080 }
4081 }
4082 }
4083 }
4084}
4085
4086/* Set route-map to the peer. */
4087int
4088peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004089 const char *name)
paul718e3742002-12-13 20:15:29 +00004090{
4091 struct bgp_filter *filter;
4092 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004093 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004094
4095 if (! peer->afc[afi][safi])
4096 return BGP_ERR_PEER_INACTIVE;
4097
paulfee0f4c2004-09-13 05:12:46 +00004098 if (direct != RMAP_IN && direct != RMAP_OUT &&
4099 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004100 return BGP_ERR_INVALID_VALUE;
4101
paulfee0f4c2004-09-13 05:12:46 +00004102 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4103 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004104 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4105
4106 filter = &peer->filter[afi][safi];
4107
4108 if (filter->map[direct].name)
4109 free (filter->map[direct].name);
4110
4111 filter->map[direct].name = strdup (name);
4112 filter->map[direct].map = route_map_lookup_by_name (name);
4113
4114 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4115 return 0;
4116
4117 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004118 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004119 {
4120 filter = &peer->filter[afi][safi];
4121
4122 if (! peer->af_group[afi][safi])
4123 continue;
4124
4125 if (filter->map[direct].name)
4126 free (filter->map[direct].name);
4127 filter->map[direct].name = strdup (name);
4128 filter->map[direct].map = route_map_lookup_by_name (name);
4129 }
4130 return 0;
4131}
4132
4133/* Unset route-map from the peer. */
4134int
4135peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4136{
4137 struct bgp_filter *filter;
4138 struct bgp_filter *gfilter;
4139 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004140 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004141
4142 if (! peer->afc[afi][safi])
4143 return BGP_ERR_PEER_INACTIVE;
4144
hassob5f29602005-05-25 21:00:28 +00004145 if (direct != RMAP_IN && direct != RMAP_OUT &&
4146 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004147 return BGP_ERR_INVALID_VALUE;
4148
hassob5f29602005-05-25 21:00:28 +00004149 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4150 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004151 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4152
4153 filter = &peer->filter[afi][safi];
4154
4155 /* apply peer-group filter */
4156 if (peer->af_group[afi][safi])
4157 {
4158 gfilter = &peer->group->conf->filter[afi][safi];
4159
4160 if (gfilter->map[direct].name)
4161 {
4162 if (filter->map[direct].name)
4163 free (filter->map[direct].name);
4164 filter->map[direct].name = strdup (gfilter->map[direct].name);
4165 filter->map[direct].map = gfilter->map[direct].map;
4166 return 0;
4167 }
4168 }
4169
4170 if (filter->map[direct].name)
4171 free (filter->map[direct].name);
4172 filter->map[direct].name = NULL;
4173 filter->map[direct].map = NULL;
4174
4175 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4176 return 0;
4177
4178 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004179 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004180 {
4181 filter = &peer->filter[afi][safi];
4182
4183 if (! peer->af_group[afi][safi])
4184 continue;
4185
4186 if (filter->map[direct].name)
4187 free (filter->map[direct].name);
4188 filter->map[direct].name = NULL;
4189 filter->map[direct].map = NULL;
4190 }
4191 return 0;
4192}
4193
4194/* Set unsuppress-map to the peer. */
4195int
paulfd79ac92004-10-13 05:06:08 +00004196peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4197 const char *name)
paul718e3742002-12-13 20:15:29 +00004198{
4199 struct bgp_filter *filter;
4200 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004201 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004202
4203 if (! peer->afc[afi][safi])
4204 return BGP_ERR_PEER_INACTIVE;
4205
4206 if (peer_is_group_member (peer, afi, safi))
4207 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4208
4209 filter = &peer->filter[afi][safi];
4210
4211 if (filter->usmap.name)
4212 free (filter->usmap.name);
4213
4214 filter->usmap.name = strdup (name);
4215 filter->usmap.map = route_map_lookup_by_name (name);
4216
4217 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4218 return 0;
4219
4220 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004221 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004222 {
4223 filter = &peer->filter[afi][safi];
4224
4225 if (! peer->af_group[afi][safi])
4226 continue;
4227
4228 if (filter->usmap.name)
4229 free (filter->usmap.name);
4230 filter->usmap.name = strdup (name);
4231 filter->usmap.map = route_map_lookup_by_name (name);
4232 }
4233 return 0;
4234}
4235
4236/* Unset route-map from the peer. */
4237int
4238peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4239{
4240 struct bgp_filter *filter;
4241 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004242 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004243
4244 if (! peer->afc[afi][safi])
4245 return BGP_ERR_PEER_INACTIVE;
4246
4247 if (peer_is_group_member (peer, afi, safi))
4248 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4249
4250 filter = &peer->filter[afi][safi];
4251
4252 if (filter->usmap.name)
4253 free (filter->usmap.name);
4254 filter->usmap.name = NULL;
4255 filter->usmap.map = NULL;
4256
4257 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4258 return 0;
4259
4260 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004261 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004262 {
4263 filter = &peer->filter[afi][safi];
4264
4265 if (! peer->af_group[afi][safi])
4266 continue;
4267
4268 if (filter->usmap.name)
4269 free (filter->usmap.name);
4270 filter->usmap.name = NULL;
4271 filter->usmap.map = NULL;
4272 }
4273 return 0;
4274}
4275
4276int
4277peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004278 u_int32_t max, u_char threshold,
4279 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004280{
4281 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004283
4284 if (! peer->afc[afi][safi])
4285 return BGP_ERR_PEER_INACTIVE;
4286
4287 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4288 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004289 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004290 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004291 if (warning)
4292 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4293 else
4294 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4295
4296 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4297 return 0;
4298
4299 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004300 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004301 {
4302 if (! peer->af_group[afi][safi])
4303 continue;
4304
4305 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4306 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004307 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004308 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004309 if (warning)
4310 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4311 else
4312 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4313 }
4314 return 0;
4315}
4316
4317int
4318peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4319{
4320 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004321 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004322
4323 if (! peer->afc[afi][safi])
4324 return BGP_ERR_PEER_INACTIVE;
4325
4326 /* apply peer-group config */
4327 if (peer->af_group[afi][safi])
4328 {
4329 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4330 PEER_FLAG_MAX_PREFIX))
4331 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4332 else
4333 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4334
4335 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4336 PEER_FLAG_MAX_PREFIX_WARNING))
4337 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4338 else
4339 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4340
4341 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004342 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004343 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004344 return 0;
4345 }
4346
4347 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4348 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4349 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004350 peer->pmax_threshold[afi][safi] = 0;
4351 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004352
4353 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4354 return 0;
4355
4356 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004357 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004358 {
4359 if (! peer->af_group[afi][safi])
4360 continue;
4361
4362 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4363 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4364 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004365 peer->pmax_threshold[afi][safi] = 0;
4366 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004367 }
4368 return 0;
4369}
4370
Nick Hilliardfa411a22011-03-23 15:33:17 +00004371/* Set # of hops between us and BGP peer. */
4372int
4373peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4374{
4375 struct peer_group *group;
4376 struct listnode *node, *nnode;
4377 struct peer *peer1;
4378 int ret;
4379
4380 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4381
4382 if (peer_sort (peer) == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004383 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004384
4385 /* We cannot configure ttl-security hops when ebgp-multihop is already
4386 set. For non peer-groups, the check is simple. For peer-groups, it's
4387 slightly messy, because we need to check both the peer-group structure
4388 and all peer-group members for any trace of ebgp-multihop configuration
4389 before actually applying the ttl-security rules. Cisco really made a
4390 mess of this configuration parameter, and OpenBGPD got it right.
4391 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004392
4393 if (peer->gtsm_hops == 0) {
4394 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4395 {
4396 group = peer->group;
4397 if (group->conf->ttl != 1)
4398 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004399
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004400 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4401 {
4402 if (peer_sort (peer1) == BGP_PEER_IBGP)
4403 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004404
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004405 if (peer1->ttl != 1)
4406 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4407 }
4408 }
4409 else
4410 {
4411 if (peer->ttl != 1)
4412 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4413 }
4414 /* specify MAXTTL on outgoing packets */
4415 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4416 if (ret != 0)
4417 return ret;
4418 }
4419
Nick Hilliardfa411a22011-03-23 15:33:17 +00004420 peer->gtsm_hops = gtsm_hops;
4421
Nick Hilliardfa411a22011-03-23 15:33:17 +00004422 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4423 {
4424 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4425 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4426 }
4427 else
4428 {
4429 group = peer->group;
4430 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4431 {
4432 if (peer_sort (peer) == BGP_PEER_IBGP)
4433 continue;
4434
4435 peer->gtsm_hops = group->conf->gtsm_hops;
4436
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004437 /* Change setting of existing peer
4438 * established then change value (may break connectivity)
4439 * not established yet (teardown session and restart)
4440 * no session then do nothing (will get handled by next connection)
4441 */
4442 if (peer->status == Established)
4443 {
4444 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4445 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4446 MAXTTL + 1 - peer->gtsm_hops);
4447 }
4448 else if (peer->status < Established)
4449 {
4450 if (BGP_DEBUG (events, EVENTS))
4451 zlog_debug ("%s Min-ttl changed", peer->host);
4452 BGP_EVENT_ADD (peer, BGP_Stop);
4453 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004454 }
4455 }
4456
4457 return 0;
4458}
4459
4460int
4461peer_ttl_security_hops_unset (struct peer *peer)
4462{
4463 struct peer_group *group;
4464 struct listnode *node, *nnode;
4465 struct peer *opeer;
4466
4467 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4468
4469 if (peer_sort (peer) == BGP_PEER_IBGP)
4470 return 0;
4471
4472 /* if a peer-group member, then reset to peer-group default rather than 0 */
4473 if (peer_group_active (peer))
4474 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4475 else
4476 peer->gtsm_hops = 0;
4477
4478 opeer = peer;
4479 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4480 {
4481 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4482 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4483 }
4484 else
4485 {
4486 group = peer->group;
4487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4488 {
4489 if (peer_sort (peer) == BGP_PEER_IBGP)
4490 continue;
4491
4492 peer->gtsm_hops = 0;
4493
4494 if (peer->fd >= 0)
4495 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4496 }
4497 }
4498
4499 return peer_ebgp_multihop_unset (opeer);
4500}
4501
paul718e3742002-12-13 20:15:29 +00004502int
4503peer_clear (struct peer *peer)
4504{
4505 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4506 {
hasso0a486e52005-02-01 20:57:17 +00004507 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4508 {
4509 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4510 if (peer->t_pmax_restart)
4511 {
4512 BGP_TIMER_OFF (peer->t_pmax_restart);
4513 if (BGP_DEBUG (events, EVENTS))
4514 zlog_debug ("%s Maximum-prefix restart timer canceled",
4515 peer->host);
4516 }
4517 BGP_EVENT_ADD (peer, BGP_Start);
4518 return 0;
4519 }
4520
paul718e3742002-12-13 20:15:29 +00004521 peer->v_start = BGP_INIT_START_TIMER;
4522 if (peer->status == Established)
4523 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4524 BGP_NOTIFY_CEASE_ADMIN_RESET);
4525 else
4526 BGP_EVENT_ADD (peer, BGP_Stop);
4527 }
4528 return 0;
4529}
4530
4531int
4532peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4533 enum bgp_clear_type stype)
4534{
4535 if (peer->status != Established)
4536 return 0;
4537
4538 if (! peer->afc[afi][safi])
4539 return BGP_ERR_AF_UNCONFIGURED;
4540
paulfee0f4c2004-09-13 05:12:46 +00004541 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4542 {
4543 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4544 return 0;
4545 bgp_check_local_routes_rsclient (peer, afi, safi);
4546 bgp_soft_reconfig_rsclient (peer, afi, safi);
4547 }
4548
paul718e3742002-12-13 20:15:29 +00004549 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4550 bgp_announce_route (peer, afi, safi);
4551
4552 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4553 {
4554 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4555 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4556 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4557 {
4558 struct bgp_filter *filter = &peer->filter[afi][safi];
4559 u_char prefix_type;
4560
4561 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4562 prefix_type = ORF_TYPE_PREFIX;
4563 else
4564 prefix_type = ORF_TYPE_PREFIX_OLD;
4565
4566 if (filter->plist[FILTER_IN].plist)
4567 {
4568 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4569 bgp_route_refresh_send (peer, afi, safi,
4570 prefix_type, REFRESH_DEFER, 1);
4571 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4572 REFRESH_IMMEDIATE, 0);
4573 }
4574 else
4575 {
4576 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4577 bgp_route_refresh_send (peer, afi, safi,
4578 prefix_type, REFRESH_IMMEDIATE, 1);
4579 else
4580 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4581 }
4582 return 0;
4583 }
4584 }
4585
4586 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4587 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4588 {
4589 /* If neighbor has soft reconfiguration inbound flag.
4590 Use Adj-RIB-In database. */
4591 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4592 bgp_soft_reconfig_in (peer, afi, safi);
4593 else
4594 {
4595 /* If neighbor has route refresh capability, send route refresh
4596 message to the peer. */
4597 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4598 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4599 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4600 else
4601 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4602 }
4603 }
4604 return 0;
4605}
4606
paulfd79ac92004-10-13 05:06:08 +00004607/* Display peer uptime.*/
4608/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004609char *
4610peer_uptime (time_t uptime2, char *buf, size_t len)
4611{
4612 time_t uptime1;
4613 struct tm *tm;
4614
4615 /* Check buffer length. */
4616 if (len < BGP_UPTIME_LEN)
4617 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004618 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004619 /* XXX: should return status instead of buf... */
4620 snprintf (buf, len, "<error> ");
4621 return buf;
paul718e3742002-12-13 20:15:29 +00004622 }
4623
4624 /* If there is no connection has been done before print `never'. */
4625 if (uptime2 == 0)
4626 {
4627 snprintf (buf, len, "never ");
4628 return buf;
4629 }
4630
4631 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004632 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004633 uptime1 -= uptime2;
4634 tm = gmtime (&uptime1);
4635
4636 /* Making formatted timer strings. */
4637#define ONE_DAY_SECOND 60*60*24
4638#define ONE_WEEK_SECOND 60*60*24*7
4639
4640 if (uptime1 < ONE_DAY_SECOND)
4641 snprintf (buf, len, "%02d:%02d:%02d",
4642 tm->tm_hour, tm->tm_min, tm->tm_sec);
4643 else if (uptime1 < ONE_WEEK_SECOND)
4644 snprintf (buf, len, "%dd%02dh%02dm",
4645 tm->tm_yday, tm->tm_hour, tm->tm_min);
4646 else
4647 snprintf (buf, len, "%02dw%dd%02dh",
4648 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4649 return buf;
4650}
4651
paul94f2b392005-06-28 12:44:16 +00004652static void
paul718e3742002-12-13 20:15:29 +00004653bgp_config_write_filter (struct vty *vty, struct peer *peer,
4654 afi_t afi, safi_t safi)
4655{
4656 struct bgp_filter *filter;
4657 struct bgp_filter *gfilter = NULL;
4658 char *addr;
4659 int in = FILTER_IN;
4660 int out = FILTER_OUT;
4661
4662 addr = peer->host;
4663 filter = &peer->filter[afi][safi];
4664 if (peer->af_group[afi][safi])
4665 gfilter = &peer->group->conf->filter[afi][safi];
4666
4667 /* distribute-list. */
4668 if (filter->dlist[in].name)
4669 if (! gfilter || ! gfilter->dlist[in].name
4670 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4671 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4672 filter->dlist[in].name, VTY_NEWLINE);
4673 if (filter->dlist[out].name && ! gfilter)
4674 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4675 filter->dlist[out].name, VTY_NEWLINE);
4676
4677 /* prefix-list. */
4678 if (filter->plist[in].name)
4679 if (! gfilter || ! gfilter->plist[in].name
4680 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4681 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4682 filter->plist[in].name, VTY_NEWLINE);
4683 if (filter->plist[out].name && ! gfilter)
4684 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4685 filter->plist[out].name, VTY_NEWLINE);
4686
4687 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004688 if (filter->map[RMAP_IN].name)
4689 if (! gfilter || ! gfilter->map[RMAP_IN].name
4690 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004691 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004692 filter->map[RMAP_IN].name, VTY_NEWLINE);
4693 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004694 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004695 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4696 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4697 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4698 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4699 if (filter->map[RMAP_EXPORT].name)
4700 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4701 || strcmp (filter->map[RMAP_EXPORT].name,
4702 gfilter->map[RMAP_EXPORT].name) != 0)
4703 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4704 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004705
4706 /* unsuppress-map */
4707 if (filter->usmap.name && ! gfilter)
4708 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4709 filter->usmap.name, VTY_NEWLINE);
4710
4711 /* filter-list. */
4712 if (filter->aslist[in].name)
4713 if (! gfilter || ! gfilter->aslist[in].name
4714 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4715 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4716 filter->aslist[in].name, VTY_NEWLINE);
4717 if (filter->aslist[out].name && ! gfilter)
4718 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4719 filter->aslist[out].name, VTY_NEWLINE);
4720}
4721
4722/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004723static void
paul718e3742002-12-13 20:15:29 +00004724bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4725 struct peer *peer, afi_t afi, safi_t safi)
4726{
paul718e3742002-12-13 20:15:29 +00004727 struct peer *g_peer = NULL;
4728 char buf[SU_ADDRSTRLEN];
4729 char *addr;
4730
paul718e3742002-12-13 20:15:29 +00004731 addr = peer->host;
4732 if (peer_group_active (peer))
4733 g_peer = peer->group->conf;
4734
4735 /************************************
4736 ****** Global to the neighbor ******
4737 ************************************/
4738 if (afi == AFI_IP && safi == SAFI_UNICAST)
4739 {
4740 /* remote-as. */
4741 if (! peer_group_active (peer))
4742 {
4743 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4744 vty_out (vty, " neighbor %s peer-group%s", addr,
4745 VTY_NEWLINE);
4746 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004747 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004748 VTY_NEWLINE);
4749 }
4750 else
4751 {
4752 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004753 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004754 VTY_NEWLINE);
4755 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4756 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4757 peer->group->name, VTY_NEWLINE);
4758 }
4759
4760 /* local-as. */
4761 if (peer->change_local_as)
4762 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004763 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004764 peer->change_local_as,
4765 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4766 " no-prepend" : "", VTY_NEWLINE);
4767
4768 /* Description. */
4769 if (peer->desc)
4770 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4771 VTY_NEWLINE);
4772
4773 /* Shutdown. */
4774 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4775 if (! peer_group_active (peer) ||
4776 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4777 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4778
Paul Jakma0df7c912008-07-21 21:02:49 +00004779 /* Password. */
4780 if (peer->password)
4781 if (!peer_group_active (peer)
4782 || ! g_peer->password
4783 || strcmp (peer->password, g_peer->password) != 0)
4784 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4785 VTY_NEWLINE);
4786
paul718e3742002-12-13 20:15:29 +00004787 /* BGP port. */
4788 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004789 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004790 VTY_NEWLINE);
4791
4792 /* Local interface name. */
4793 if (peer->ifname)
4794 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4795 VTY_NEWLINE);
4796
4797 /* Passive. */
4798 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4799 if (! peer_group_active (peer) ||
4800 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4801 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4802
4803 /* EBGP multihop. */
Nick Hilliardfa411a22011-03-23 15:33:17 +00004804 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
4805 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004806 if (! peer_group_active (peer) ||
4807 g_peer->ttl != peer->ttl)
4808 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4809 VTY_NEWLINE);
4810
Nick Hilliardfa411a22011-03-23 15:33:17 +00004811 /* ttl-security hops */
4812 if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
4813 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004814 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004815 peer->gtsm_hops, VTY_NEWLINE);
4816
hasso6ffd2072005-02-02 14:50:11 +00004817 /* disable-connected-check. */
4818 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004819 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004820 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4821 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004822
4823 /* Update-source. */
4824 if (peer->update_if)
4825 if (! peer_group_active (peer) || ! g_peer->update_if
4826 || strcmp (g_peer->update_if, peer->update_if) != 0)
4827 vty_out (vty, " neighbor %s update-source %s%s", addr,
4828 peer->update_if, VTY_NEWLINE);
4829 if (peer->update_source)
4830 if (! peer_group_active (peer) || ! g_peer->update_source
4831 || sockunion_cmp (g_peer->update_source,
4832 peer->update_source) != 0)
4833 vty_out (vty, " neighbor %s update-source %s%s", addr,
4834 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4835 VTY_NEWLINE);
4836
paul718e3742002-12-13 20:15:29 +00004837 /* advertisement-interval */
4838 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4839 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4840 addr, peer->v_routeadv, VTY_NEWLINE);
4841
4842 /* timers. */
4843 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4844 && ! peer_group_active (peer))
4845 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4846 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4847
4848 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4849 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4850 peer->connect, VTY_NEWLINE);
4851
4852 /* Default weight. */
4853 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4854 if (! peer_group_active (peer) ||
4855 g_peer->weight != peer->weight)
4856 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4857 VTY_NEWLINE);
4858
paul718e3742002-12-13 20:15:29 +00004859 /* Dynamic capability. */
4860 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4861 if (! peer_group_active (peer) ||
4862 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4863 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4864 VTY_NEWLINE);
4865
4866 /* dont capability negotiation. */
4867 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4868 if (! peer_group_active (peer) ||
4869 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4870 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4871 VTY_NEWLINE);
4872
4873 /* override capability negotiation. */
4874 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4875 if (! peer_group_active (peer) ||
4876 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4877 vty_out (vty, " neighbor %s override-capability%s", addr,
4878 VTY_NEWLINE);
4879
4880 /* strict capability negotiation. */
4881 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4882 if (! peer_group_active (peer) ||
4883 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4884 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4885 VTY_NEWLINE);
4886
4887 if (! peer_group_active (peer))
4888 {
4889 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4890 {
4891 if (peer->afc[AFI_IP][SAFI_UNICAST])
4892 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4893 }
4894 else
4895 {
4896 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4897 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4898 }
4899 }
4900 }
4901
4902
4903 /************************************
4904 ****** Per AF to the neighbor ******
4905 ************************************/
4906
4907 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4908 {
4909 if (peer->af_group[afi][safi])
4910 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4911 peer->group->name, VTY_NEWLINE);
4912 else
4913 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4914 }
4915
4916 /* ORF capability. */
4917 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4918 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4919 if (! peer->af_group[afi][safi])
4920 {
4921 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4922
4923 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4924 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4925 vty_out (vty, " both");
4926 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4927 vty_out (vty, " send");
4928 else
4929 vty_out (vty, " receive");
4930 vty_out (vty, "%s", VTY_NEWLINE);
4931 }
4932
4933 /* Route reflector client. */
4934 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4935 && ! peer->af_group[afi][safi])
4936 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4937 VTY_NEWLINE);
4938
4939 /* Nexthop self. */
4940 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4941 && ! peer->af_group[afi][safi])
4942 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4943
4944 /* Remove private AS. */
4945 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4946 && ! peer->af_group[afi][safi])
4947 vty_out (vty, " neighbor %s remove-private-AS%s",
4948 addr, VTY_NEWLINE);
4949
4950 /* send-community print. */
4951 if (! peer->af_group[afi][safi])
4952 {
4953 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4954 {
4955 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4956 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4957 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4958 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4959 vty_out (vty, " neighbor %s send-community extended%s",
4960 addr, VTY_NEWLINE);
4961 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4962 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4963 }
4964 else
4965 {
4966 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4967 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4968 vty_out (vty, " no neighbor %s send-community both%s",
4969 addr, VTY_NEWLINE);
4970 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4971 vty_out (vty, " no neighbor %s send-community extended%s",
4972 addr, VTY_NEWLINE);
4973 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4974 vty_out (vty, " no neighbor %s send-community%s",
4975 addr, VTY_NEWLINE);
4976 }
4977 }
4978
4979 /* Default information */
4980 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4981 && ! peer->af_group[afi][safi])
4982 {
4983 vty_out (vty, " neighbor %s default-originate", addr);
4984 if (peer->default_rmap[afi][safi].name)
4985 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4986 vty_out (vty, "%s", VTY_NEWLINE);
4987 }
4988
4989 /* Soft reconfiguration inbound. */
4990 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4991 if (! peer->af_group[afi][safi] ||
4992 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4993 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4994 VTY_NEWLINE);
4995
4996 /* maximum-prefix. */
4997 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4998 if (! peer->af_group[afi][safi]
4999 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005000 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005001 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5002 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005003 {
hasso0a486e52005-02-01 20:57:17 +00005004 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5005 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5006 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5007 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5008 vty_out (vty, " warning-only");
5009 if (peer->pmax_restart[afi][safi])
5010 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5011 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005012 }
paul718e3742002-12-13 20:15:29 +00005013
5014 /* Route server client. */
5015 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5016 && ! peer->af_group[afi][safi])
5017 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5018
Dylan Hall3cf12882011-10-27 15:28:17 +04005019 /* Nexthop-local unchanged. */
5020 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5021 && ! peer->af_group[afi][safi])
5022 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5023
paul718e3742002-12-13 20:15:29 +00005024 /* Allow AS in. */
5025 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5026 if (! peer_group_active (peer)
5027 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5028 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5029 {
5030 if (peer->allowas_in[afi][safi] == 3)
5031 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5032 else
5033 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5034 peer->allowas_in[afi][safi], VTY_NEWLINE);
5035 }
5036
5037 /* Filter. */
5038 bgp_config_write_filter (vty, peer, afi, safi);
5039
5040 /* atribute-unchanged. */
5041 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5042 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5043 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5044 && ! peer->af_group[afi][safi])
5045 {
5046 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5047 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5048 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5049 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5050 else
5051 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5052 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5053 " as-path" : "",
5054 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5055 " next-hop" : "",
5056 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5057 " med" : "", VTY_NEWLINE);
5058 }
5059}
5060
5061/* Display "address-family" configuration header. */
5062void
5063bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5064 int *write)
5065{
5066 if (*write)
5067 return;
5068
5069 if (afi == AFI_IP && safi == SAFI_UNICAST)
5070 return;
5071
5072 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5073
5074 if (afi == AFI_IP)
5075 {
5076 if (safi == SAFI_MULTICAST)
5077 vty_out (vty, "ipv4 multicast");
5078 else if (safi == SAFI_MPLS_VPN)
5079 vty_out (vty, "vpnv4 unicast");
5080 }
5081 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005082 {
5083 vty_out (vty, "ipv6");
5084
5085 if (safi == SAFI_MULTICAST)
5086 vty_out (vty, " multicast");
5087 }
paul718e3742002-12-13 20:15:29 +00005088
5089 vty_out (vty, "%s", VTY_NEWLINE);
5090
5091 *write = 1;
5092}
5093
5094/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005095static int
paul718e3742002-12-13 20:15:29 +00005096bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5097 safi_t safi)
5098{
5099 int write = 0;
5100 struct peer *peer;
5101 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005102 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005103
5104 bgp_config_write_network (vty, bgp, afi, safi, &write);
5105
5106 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5107
paul1eb8ef22005-04-07 07:30:20 +00005108 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005109 {
5110 if (group->conf->afc[afi][safi])
5111 {
5112 bgp_config_write_family_header (vty, afi, safi, &write);
5113 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5114 }
5115 }
paul1eb8ef22005-04-07 07:30:20 +00005116 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005117 {
5118 if (peer->afc[afi][safi])
5119 {
5120 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5121 {
5122 bgp_config_write_family_header (vty, afi, safi, &write);
5123 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5124 }
5125 }
5126 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005127
5128 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5129
paul718e3742002-12-13 20:15:29 +00005130 if (write)
5131 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5132
5133 return write;
5134}
5135
5136int
5137bgp_config_write (struct vty *vty)
5138{
5139 int write = 0;
5140 struct bgp *bgp;
5141 struct peer_group *group;
5142 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005143 struct listnode *node, *nnode;
5144 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005145
5146 /* BGP Multiple instance. */
5147 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5148 {
5149 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5150 write++;
5151 }
5152
5153 /* BGP Config type. */
5154 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5155 {
5156 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5157 write++;
5158 }
5159
5160 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005161 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005162 {
5163 if (write)
5164 vty_out (vty, "!%s", VTY_NEWLINE);
5165
5166 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005167 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005168
5169 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5170 {
5171 if (bgp->name)
5172 vty_out (vty, " view %s", bgp->name);
5173 }
5174 vty_out (vty, "%s", VTY_NEWLINE);
5175
5176 /* No Synchronization */
5177 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5178 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5179
5180 /* BGP fast-external-failover. */
5181 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5182 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5183
5184 /* BGP router ID. */
5185 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5186 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5187 VTY_NEWLINE);
5188
paul848973c2003-08-13 00:32:49 +00005189 /* BGP log-neighbor-changes. */
5190 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5191 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5192
paul718e3742002-12-13 20:15:29 +00005193 /* BGP configuration. */
5194 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5195 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5196
5197 /* BGP default ipv4-unicast. */
5198 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5199 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5200
5201 /* BGP default local-preference. */
5202 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5203 vty_out (vty, " bgp default local-preference %d%s",
5204 bgp->default_local_pref, VTY_NEWLINE);
5205
5206 /* BGP client-to-client reflection. */
5207 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5208 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5209
5210 /* BGP cluster ID. */
5211 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5212 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5213 VTY_NEWLINE);
5214
hassoe0701b72004-05-20 09:19:34 +00005215 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005216 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005217 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5218 VTY_NEWLINE);
5219
5220 /* Confederation peer */
5221 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005222 {
hassoe0701b72004-05-20 09:19:34 +00005223 int i;
paul718e3742002-12-13 20:15:29 +00005224
hassoe0701b72004-05-20 09:19:34 +00005225 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005226
hassoe0701b72004-05-20 09:19:34 +00005227 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005228 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005229
hassoe0701b72004-05-20 09:19:34 +00005230 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005231 }
5232
5233 /* BGP enforce-first-as. */
5234 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5235 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5236
5237 /* BGP deterministic-med. */
5238 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5239 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005240
5241 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005242 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5243 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5244 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005245 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5246 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5247
paul718e3742002-12-13 20:15:29 +00005248 /* BGP bestpath method. */
5249 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5250 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005251 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5252 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005253 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5254 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5255 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5256 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5257 {
5258 vty_out (vty, " bgp bestpath med");
5259 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5260 vty_out (vty, " confed");
5261 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5262 vty_out (vty, " missing-as-worst");
5263 vty_out (vty, "%s", VTY_NEWLINE);
5264 }
5265
5266 /* BGP network import check. */
5267 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5268 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5269
5270 /* BGP scan interval. */
5271 bgp_config_write_scan_time (vty);
5272
5273 /* BGP flag dampening. */
5274 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5275 BGP_CONFIG_DAMPENING))
5276 bgp_config_write_damp (vty);
5277
5278 /* BGP static route configuration. */
5279 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5280
5281 /* BGP redistribute configuration. */
5282 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5283
5284 /* BGP timers configuration. */
5285 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5286 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5287 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5288 bgp->default_holdtime, VTY_NEWLINE);
5289
5290 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005291 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005292 {
5293 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5294 }
5295
5296 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005297 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005298 {
5299 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5300 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5301 }
5302
Josh Bailey165b5ff2011-07-20 20:43:22 -07005303 /* maximum-paths */
5304 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5305
paul718e3742002-12-13 20:15:29 +00005306 /* Distance configuration. */
5307 bgp_config_write_distance (vty, bgp);
5308
5309 /* No auto-summary */
5310 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5311 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5312
5313 /* IPv4 multicast configuration. */
5314 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5315
5316 /* IPv4 VPN configuration. */
5317 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5318
5319 /* IPv6 unicast configuration. */
5320 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5321
Paul Jakma37a217a2007-04-10 19:20:29 +00005322 /* IPv6 multicast configuration. */
5323 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5324
paul718e3742002-12-13 20:15:29 +00005325 write++;
5326 }
5327 return write;
5328}
5329
5330void
paul94f2b392005-06-28 12:44:16 +00005331bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005332{
5333 memset (&bgp_master, 0, sizeof (struct bgp_master));
5334
5335 bm = &bgp_master;
5336 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005337 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005338 bm->port = BGP_PORT_DEFAULT;
5339 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005340 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005341}
paul200df112005-06-01 11:17:05 +00005342
paul718e3742002-12-13 20:15:29 +00005343
5344void
paul94f2b392005-06-28 12:44:16 +00005345bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005346{
paul718e3742002-12-13 20:15:29 +00005347 /* BGP VTY commands installation. */
5348 bgp_vty_init ();
5349
paul718e3742002-12-13 20:15:29 +00005350 /* Init zebra. */
5351 bgp_zebra_init ();
5352
5353 /* BGP inits. */
5354 bgp_attr_init ();
5355 bgp_debug_init ();
5356 bgp_dump_init ();
5357 bgp_route_init ();
5358 bgp_route_map_init ();
5359 bgp_scan_init ();
5360 bgp_mplsvpn_init ();
5361
5362 /* Access list initialize. */
5363 access_list_init ();
5364 access_list_add_hook (peer_distribute_update);
5365 access_list_delete_hook (peer_distribute_update);
5366
5367 /* Filter list initialize. */
5368 bgp_filter_init ();
5369 as_list_add_hook (peer_aslist_update);
5370 as_list_delete_hook (peer_aslist_update);
5371
5372 /* Prefix list initialize.*/
5373 prefix_list_init ();
5374 prefix_list_add_hook (peer_prefix_list_update);
5375 prefix_list_delete_hook (peer_prefix_list_update);
5376
5377 /* Community list initialize. */
5378 bgp_clist = community_list_init ();
5379
5380#ifdef HAVE_SNMP
5381 bgp_snmp_init ();
5382#endif /* HAVE_SNMP */
5383}
paul545acaf2004-04-20 15:13:15 +00005384
5385void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005386bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005387{
paul545acaf2004-04-20 15:13:15 +00005388 struct bgp *bgp;
5389 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005390 struct listnode *node, *nnode;
5391 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005392
paul1eb8ef22005-04-07 07:30:20 +00005393 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5394 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005395 if (peer->status == Established)
5396 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5397 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005398
paul545acaf2004-04-20 15:13:15 +00005399 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005400
paule210cf92005-06-15 19:15:35 +00005401 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005402 {
5403 work_queue_free (bm->process_main_queue);
5404 bm->process_main_queue = NULL;
5405 }
paule210cf92005-06-15 19:15:35 +00005406 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005407 {
5408 work_queue_free (bm->process_rsclient_queue);
5409 bm->process_rsclient_queue = NULL;
5410 }
paul545acaf2004-04-20 15:13:15 +00005411}