blob: ab27783fa84439dd6f41e3cb3bd46c0796de18b7 [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
paul718e3742002-12-13 20:15:29 +00002058 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002059
2060 return 0;
2061}
2062
2063/* Delete BGP instance. */
2064int
2065bgp_delete (struct bgp *bgp)
2066{
2067 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002068 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002069 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002070 struct listnode *next;
2071 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002072 int i;
2073
2074 /* Delete static route. */
2075 bgp_static_delete (bgp);
2076
2077 /* Unset redistribution. */
2078 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2079 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2080 if (i != ZEBRA_ROUTE_BGP)
2081 bgp_redistribute_unset (bgp, afi, i);
2082
paul1eb8ef22005-04-07 07:30:20 +00002083 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2084 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002085
Chris Caputo228da422009-07-18 05:44:03 +00002086 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2087 peer_group_delete (group);
2088
2089 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002090
2091 if (bgp->peer_self) {
2092 peer_delete(bgp->peer_self);
2093 bgp->peer_self = NULL;
2094 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002095
2096 /* Remove visibility via the master list - there may however still be
2097 * routes to be processed still referencing the struct bgp.
2098 */
2099 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002100 if (list_isempty(bm->bgp))
2101 bgp_close ();
2102
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002103 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002104
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002105 return 0;
2106}
2107
2108static void bgp_free (struct bgp *);
2109
2110void
2111bgp_lock (struct bgp *bgp)
2112{
2113 ++bgp->lock;
2114}
2115
2116void
2117bgp_unlock(struct bgp *bgp)
2118{
Chris Caputo228da422009-07-18 05:44:03 +00002119 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002120 if (--bgp->lock == 0)
2121 bgp_free (bgp);
2122}
2123
2124static void
2125bgp_free (struct bgp *bgp)
2126{
2127 afi_t afi;
2128 safi_t safi;
2129
2130 list_delete (bgp->group);
2131 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002132 list_delete (bgp->rsclient);
2133
paul718e3742002-12-13 20:15:29 +00002134 if (bgp->name)
2135 free (bgp->name);
2136
2137 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2138 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2139 {
2140 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002141 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002142 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002143 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002144 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002145 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002146 }
2147 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002148}
2149
2150struct peer *
2151peer_lookup (struct bgp *bgp, union sockunion *su)
2152{
2153 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002155
Steve Hillfc4dc592009-07-28 17:54:35 +01002156 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002157 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002158 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2159 if (sockunion_same (&peer->su, su)
2160 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2161 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002162 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002163 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002164 {
2165 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002166
Paul Jakma2158ad22009-07-28 18:10:55 +01002167 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2168 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2169 if (sockunion_same (&peer->su, su)
2170 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2171 return peer;
paul718e3742002-12-13 20:15:29 +00002172 }
2173 return NULL;
2174}
2175
2176struct peer *
2177peer_lookup_with_open (union sockunion *su, as_t remote_as,
2178 struct in_addr *remote_id, int *as)
2179{
2180 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002181 struct listnode *node;
2182 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002183 struct bgp *bgp;
2184
Steve Hillfc4dc592009-07-28 17:54:35 +01002185 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002186 return NULL;
2187
Paul Jakma9d878772009-08-05 16:25:16 +01002188 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002189 {
Paul Jakma9d878772009-08-05 16:25:16 +01002190 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2191 {
2192 if (sockunion_same (&peer->su, su)
2193 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2194 {
2195 if (peer->as == remote_as
2196 && peer->remote_id.s_addr == remote_id->s_addr)
2197 return peer;
2198 if (peer->as == remote_as)
2199 *as = 1;
2200 }
2201 }
2202
2203 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2204 {
2205 if (sockunion_same (&peer->su, su)
2206 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2207 {
2208 if (peer->as == remote_as
2209 && peer->remote_id.s_addr == 0)
2210 return peer;
2211 if (peer->as == remote_as)
2212 *as = 1;
2213 }
2214 }
paul718e3742002-12-13 20:15:29 +00002215 }
2216 return NULL;
2217}
2218
2219/* If peer is configured at least one address family return 1. */
2220int
2221peer_active (struct peer *peer)
2222{
2223 if (peer->afc[AFI_IP][SAFI_UNICAST]
2224 || peer->afc[AFI_IP][SAFI_MULTICAST]
2225 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2226 || peer->afc[AFI_IP6][SAFI_UNICAST]
2227 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2228 return 1;
2229 return 0;
2230}
2231
2232/* If peer is negotiated at least one address family return 1. */
2233int
2234peer_active_nego (struct peer *peer)
2235{
2236 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2237 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2238 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2239 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2240 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2241 return 1;
2242 return 0;
2243}
2244
2245/* peer_flag_change_type. */
2246enum peer_change_type
2247{
2248 peer_change_none,
2249 peer_change_reset,
2250 peer_change_reset_in,
2251 peer_change_reset_out,
2252};
2253
paul94f2b392005-06-28 12:44:16 +00002254static void
paul718e3742002-12-13 20:15:29 +00002255peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2256 enum peer_change_type type)
2257{
2258 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2259 return;
2260
2261 if (type == peer_change_reset)
2262 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2263 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2264 else if (type == peer_change_reset_in)
2265 {
2266 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2267 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2268 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2269 else
2270 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2271 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2272 }
2273 else if (type == peer_change_reset_out)
2274 bgp_announce_route (peer, afi, safi);
2275}
2276
2277struct peer_flag_action
2278{
2279 /* Peer's flag. */
2280 u_int32_t flag;
2281
2282 /* This flag can be set for peer-group member. */
2283 u_char not_for_member;
2284
2285 /* Action when the flag is changed. */
2286 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002287
2288 /* Peer down cause */
2289 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002290};
2291
Stephen Hemminger03621952009-07-21 16:27:20 -07002292static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002293 {
2294 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2295 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2296 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2297 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2298 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002299 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002300 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002301 { 0, 0, 0 }
2302 };
2303
Stephen Hemminger03621952009-07-21 16:27:20 -07002304static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002305 {
2306 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2307 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2308 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2309 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2310 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2311 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2312 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2313 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2314 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2315 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2316 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2317 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2318 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002319 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002320 { 0, 0, 0 }
2321 };
2322
2323/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002324static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002325peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002326 struct peer_flag_action *action, u_int32_t flag)
2327{
2328 int i;
2329 int found = 0;
2330 int reset_in = 0;
2331 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002332 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002333
2334 /* Check peer's frag action. */
2335 for (i = 0; i < size; i++)
2336 {
2337 match = &action_list[i];
2338
2339 if (match->flag == 0)
2340 break;
2341
2342 if (match->flag & flag)
2343 {
2344 found = 1;
2345
2346 if (match->type == peer_change_reset_in)
2347 reset_in = 1;
2348 if (match->type == peer_change_reset_out)
2349 reset_out = 1;
2350 if (match->type == peer_change_reset)
2351 {
2352 reset_in = 1;
2353 reset_out = 1;
2354 }
2355 if (match->not_for_member)
2356 action->not_for_member = 1;
2357 }
2358 }
2359
2360 /* Set peer clear type. */
2361 if (reset_in && reset_out)
2362 action->type = peer_change_reset;
2363 else if (reset_in)
2364 action->type = peer_change_reset_in;
2365 else if (reset_out)
2366 action->type = peer_change_reset_out;
2367 else
2368 action->type = peer_change_none;
2369
2370 return found;
2371}
2372
paul94f2b392005-06-28 12:44:16 +00002373static void
paul718e3742002-12-13 20:15:29 +00002374peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2375{
2376 if (flag == PEER_FLAG_SHUTDOWN)
2377 {
2378 if (CHECK_FLAG (peer->flags, flag))
2379 {
hasso93406d82005-02-02 14:40:33 +00002380 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2381 peer_nsf_stop (peer);
2382
hasso0a486e52005-02-01 20:57:17 +00002383 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2384 if (peer->t_pmax_restart)
2385 {
2386 BGP_TIMER_OFF (peer->t_pmax_restart);
2387 if (BGP_DEBUG (events, EVENTS))
2388 zlog_debug ("%s Maximum-prefix restart timer canceled",
2389 peer->host);
2390 }
2391
hasso93406d82005-02-02 14:40:33 +00002392 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2393 peer_nsf_stop (peer);
2394
paul718e3742002-12-13 20:15:29 +00002395 if (peer->status == Established)
2396 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2397 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2398 else
2399 BGP_EVENT_ADD (peer, BGP_Stop);
2400 }
2401 else
2402 {
2403 peer->v_start = BGP_INIT_START_TIMER;
2404 BGP_EVENT_ADD (peer, BGP_Stop);
2405 }
2406 }
2407 else if (peer->status == Established)
2408 {
hassoc9502432005-02-01 22:01:48 +00002409 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2410 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2411 else if (flag == PEER_FLAG_PASSIVE)
2412 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002413 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002414 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002415
hassoc9502432005-02-01 22:01:48 +00002416 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2417 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002418 }
2419 else
2420 BGP_EVENT_ADD (peer, BGP_Stop);
2421}
2422
2423/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002424static int
paul718e3742002-12-13 20:15:29 +00002425peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2426{
2427 int found;
2428 int size;
2429 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002430 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002431 struct peer_flag_action action;
2432
2433 memset (&action, 0, sizeof (struct peer_flag_action));
2434 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2435
2436 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2437
2438 /* No flag action is found. */
2439 if (! found)
2440 return BGP_ERR_INVALID_FLAG;
2441
2442 /* Not for peer-group member. */
2443 if (action.not_for_member && peer_group_active (peer))
2444 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2445
2446 /* When unset the peer-group member's flag we have to check
2447 peer-group configuration. */
2448 if (! set && peer_group_active (peer))
2449 if (CHECK_FLAG (peer->group->conf->flags, flag))
2450 {
2451 if (flag == PEER_FLAG_SHUTDOWN)
2452 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2453 else
2454 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2455 }
2456
2457 /* Flag conflict check. */
2458 if (set
2459 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2460 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2461 return BGP_ERR_PEER_FLAG_CONFLICT;
2462
2463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2464 {
2465 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2466 return 0;
2467 if (! set && ! CHECK_FLAG (peer->flags, flag))
2468 return 0;
2469 }
2470
2471 if (set)
2472 SET_FLAG (peer->flags, flag);
2473 else
2474 UNSET_FLAG (peer->flags, flag);
2475
2476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2477 {
2478 if (action.type == peer_change_reset)
2479 peer_flag_modify_action (peer, flag);
2480
2481 return 0;
2482 }
2483
2484 /* peer-group member updates. */
2485 group = peer->group;
2486
paul1eb8ef22005-04-07 07:30:20 +00002487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002488 {
2489 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2490 continue;
2491
2492 if (! set && ! CHECK_FLAG (peer->flags, flag))
2493 continue;
2494
2495 if (set)
2496 SET_FLAG (peer->flags, flag);
2497 else
2498 UNSET_FLAG (peer->flags, flag);
2499
2500 if (action.type == peer_change_reset)
2501 peer_flag_modify_action (peer, flag);
2502 }
2503 return 0;
2504}
2505
2506int
2507peer_flag_set (struct peer *peer, u_int32_t flag)
2508{
2509 return peer_flag_modify (peer, flag, 1);
2510}
2511
2512int
2513peer_flag_unset (struct peer *peer, u_int32_t flag)
2514{
2515 return peer_flag_modify (peer, flag, 0);
2516}
2517
paul94f2b392005-06-28 12:44:16 +00002518static int
paul718e3742002-12-13 20:15:29 +00002519peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2520{
2521 if (peer->af_group[afi][safi])
2522 return 1;
2523 return 0;
2524}
2525
paul94f2b392005-06-28 12:44:16 +00002526static int
paul718e3742002-12-13 20:15:29 +00002527peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2528 int set)
2529{
2530 int found;
2531 int size;
paul1eb8ef22005-04-07 07:30:20 +00002532 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002533 struct peer_group *group;
2534 struct peer_flag_action action;
2535
2536 memset (&action, 0, sizeof (struct peer_flag_action));
2537 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2538
2539 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2540
2541 /* No flag action is found. */
2542 if (! found)
2543 return BGP_ERR_INVALID_FLAG;
2544
2545 /* Adress family must be activated. */
2546 if (! peer->afc[afi][safi])
2547 return BGP_ERR_PEER_INACTIVE;
2548
2549 /* Not for peer-group member. */
2550 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2551 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2552
2553 /* Spcecial check for reflector client. */
2554 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2555 && peer_sort (peer) != BGP_PEER_IBGP)
2556 return BGP_ERR_NOT_INTERNAL_PEER;
2557
2558 /* Spcecial check for remove-private-AS. */
2559 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2560 && peer_sort (peer) == BGP_PEER_IBGP)
2561 return BGP_ERR_REMOVE_PRIVATE_AS;
2562
2563 /* When unset the peer-group member's flag we have to check
2564 peer-group configuration. */
2565 if (! set && peer->af_group[afi][safi])
2566 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2567 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2568
2569 /* When current flag configuration is same as requested one. */
2570 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2571 {
2572 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2573 return 0;
2574 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2575 return 0;
2576 }
2577
2578 if (set)
2579 SET_FLAG (peer->af_flags[afi][safi], flag);
2580 else
2581 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2582
2583 /* Execute action when peer is established. */
2584 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2585 && peer->status == Established)
2586 {
2587 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2588 bgp_clear_adj_in (peer, afi, safi);
2589 else
hassoe0701b72004-05-20 09:19:34 +00002590 {
2591 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2592 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2593 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2594 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2595 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2596 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2597 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2598 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2599
2600 peer_change_action (peer, afi, safi, action.type);
2601 }
2602
paul718e3742002-12-13 20:15:29 +00002603 }
2604
2605 /* Peer group member updates. */
2606 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2607 {
2608 group = peer->group;
2609
paul1eb8ef22005-04-07 07:30:20 +00002610 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002611 {
2612 if (! peer->af_group[afi][safi])
2613 continue;
2614
2615 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2616 continue;
2617
2618 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2619 continue;
2620
2621 if (set)
2622 SET_FLAG (peer->af_flags[afi][safi], flag);
2623 else
2624 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2625
2626 if (peer->status == Established)
2627 {
2628 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2629 bgp_clear_adj_in (peer, afi, safi);
2630 else
hassoe0701b72004-05-20 09:19:34 +00002631 {
2632 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2633 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2634 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2635 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2636 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2637 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2638 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2639 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2640
2641 peer_change_action (peer, afi, safi, action.type);
2642 }
paul718e3742002-12-13 20:15:29 +00002643 }
2644 }
2645 }
2646 return 0;
2647}
2648
2649int
2650peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2651{
2652 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2653}
2654
2655int
2656peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2657{
2658 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2659}
2660
2661/* EBGP multihop configuration. */
2662int
2663peer_ebgp_multihop_set (struct peer *peer, int ttl)
2664{
2665 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002666 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002667 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002668
2669 if (peer_sort (peer) == BGP_PEER_IBGP)
2670 return 0;
2671
Nick Hilliardfa411a22011-03-23 15:33:17 +00002672 /* see comment in peer_ttl_security_hops_set() */
2673 if (ttl != MAXTTL)
2674 {
2675 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2676 {
2677 group = peer->group;
2678 if (group->conf->gtsm_hops != 0)
2679 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2680
2681 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2682 {
2683 if (peer_sort (peer1) == BGP_PEER_IBGP)
2684 continue;
2685
2686 if (peer1->gtsm_hops != 0)
2687 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2688 }
2689 }
2690 else
2691 {
2692 if (peer->gtsm_hops != 0)
2693 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2694 }
2695 }
2696
paul718e3742002-12-13 20:15:29 +00002697 peer->ttl = ttl;
2698
2699 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2700 {
pauleb821182004-05-01 08:44:08 +00002701 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2702 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002703 }
2704 else
2705 {
2706 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002707 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002708 {
2709 if (peer_sort (peer) == BGP_PEER_IBGP)
2710 continue;
paul718e3742002-12-13 20:15:29 +00002711
pauleb821182004-05-01 08:44:08 +00002712 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002713
pauleb821182004-05-01 08:44:08 +00002714 if (peer->fd >= 0)
2715 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2716 }
paul718e3742002-12-13 20:15:29 +00002717 }
2718 return 0;
2719}
2720
2721int
2722peer_ebgp_multihop_unset (struct peer *peer)
2723{
2724 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002725 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002726
2727 if (peer_sort (peer) == BGP_PEER_IBGP)
2728 return 0;
2729
Nick Hilliardfa411a22011-03-23 15:33:17 +00002730 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2731 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2732
paul718e3742002-12-13 20:15:29 +00002733 if (peer_group_active (peer))
2734 peer->ttl = peer->group->conf->ttl;
2735 else
2736 peer->ttl = 1;
2737
2738 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2739 {
pauleb821182004-05-01 08:44:08 +00002740 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2741 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002742 }
2743 else
2744 {
2745 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002747 {
2748 if (peer_sort (peer) == BGP_PEER_IBGP)
2749 continue;
paul718e3742002-12-13 20:15:29 +00002750
pauleb821182004-05-01 08:44:08 +00002751 peer->ttl = 1;
2752
2753 if (peer->fd >= 0)
2754 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2755 }
paul718e3742002-12-13 20:15:29 +00002756 }
2757 return 0;
2758}
2759
2760/* Neighbor description. */
2761int
2762peer_description_set (struct peer *peer, char *desc)
2763{
2764 if (peer->desc)
2765 XFREE (MTYPE_PEER_DESC, peer->desc);
2766
2767 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2768
2769 return 0;
2770}
2771
2772int
2773peer_description_unset (struct peer *peer)
2774{
2775 if (peer->desc)
2776 XFREE (MTYPE_PEER_DESC, peer->desc);
2777
2778 peer->desc = NULL;
2779
2780 return 0;
2781}
2782
2783/* Neighbor update-source. */
2784int
paulfd79ac92004-10-13 05:06:08 +00002785peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002786{
2787 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002788 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002789
2790 if (peer->update_if)
2791 {
2792 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2793 && strcmp (peer->update_if, ifname) == 0)
2794 return 0;
2795
2796 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2797 peer->update_if = NULL;
2798 }
2799
2800 if (peer->update_source)
2801 {
2802 sockunion_free (peer->update_source);
2803 peer->update_source = NULL;
2804 }
2805
2806 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2807
2808 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2809 {
2810 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002811 {
2812 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2813 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2814 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2815 }
paul718e3742002-12-13 20:15:29 +00002816 else
2817 BGP_EVENT_ADD (peer, BGP_Stop);
2818 return 0;
2819 }
2820
2821 /* peer-group member updates. */
2822 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002823 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002824 {
2825 if (peer->update_if)
2826 {
2827 if (strcmp (peer->update_if, ifname) == 0)
2828 continue;
2829
2830 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2831 peer->update_if = NULL;
2832 }
2833
2834 if (peer->update_source)
2835 {
2836 sockunion_free (peer->update_source);
2837 peer->update_source = NULL;
2838 }
2839
2840 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2841
2842 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002843 {
2844 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2845 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2846 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2847 }
paul718e3742002-12-13 20:15:29 +00002848 else
2849 BGP_EVENT_ADD (peer, BGP_Stop);
2850 }
2851 return 0;
2852}
2853
2854int
2855peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2856{
2857 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002858 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002859
2860 if (peer->update_source)
2861 {
2862 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2863 && sockunion_cmp (peer->update_source, su) == 0)
2864 return 0;
2865 sockunion_free (peer->update_source);
2866 peer->update_source = NULL;
2867 }
2868
2869 if (peer->update_if)
2870 {
2871 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2872 peer->update_if = NULL;
2873 }
2874
2875 peer->update_source = sockunion_dup (su);
2876
2877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2878 {
2879 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002880 {
2881 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2882 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2883 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2884 }
paul718e3742002-12-13 20:15:29 +00002885 else
2886 BGP_EVENT_ADD (peer, BGP_Stop);
2887 return 0;
2888 }
2889
2890 /* peer-group member updates. */
2891 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002892 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002893 {
2894 if (peer->update_source)
2895 {
2896 if (sockunion_cmp (peer->update_source, su) == 0)
2897 continue;
2898 sockunion_free (peer->update_source);
2899 peer->update_source = NULL;
2900 }
2901
2902 if (peer->update_if)
2903 {
2904 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2905 peer->update_if = NULL;
2906 }
2907
2908 peer->update_source = sockunion_dup (su);
2909
2910 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002911 {
2912 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2913 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2914 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2915 }
paul718e3742002-12-13 20:15:29 +00002916 else
2917 BGP_EVENT_ADD (peer, BGP_Stop);
2918 }
2919 return 0;
2920}
2921
2922int
2923peer_update_source_unset (struct peer *peer)
2924{
2925 union sockunion *su;
2926 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002927 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002928
2929 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2930 && ! peer->update_source
2931 && ! peer->update_if)
2932 return 0;
2933
2934 if (peer->update_source)
2935 {
2936 sockunion_free (peer->update_source);
2937 peer->update_source = NULL;
2938 }
2939 if (peer->update_if)
2940 {
2941 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2942 peer->update_if = NULL;
2943 }
2944
2945 if (peer_group_active (peer))
2946 {
2947 group = peer->group;
2948
2949 if (group->conf->update_source)
2950 {
2951 su = sockunion_dup (group->conf->update_source);
2952 peer->update_source = su;
2953 }
2954 else if (group->conf->update_if)
2955 peer->update_if =
2956 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2957 }
2958
2959 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2960 {
2961 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002962 {
2963 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2964 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2965 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2966 }
paul718e3742002-12-13 20:15:29 +00002967 else
2968 BGP_EVENT_ADD (peer, BGP_Stop);
2969 return 0;
2970 }
2971
2972 /* peer-group member updates. */
2973 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002974 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002975 {
2976 if (! peer->update_source && ! peer->update_if)
2977 continue;
2978
2979 if (peer->update_source)
2980 {
2981 sockunion_free (peer->update_source);
2982 peer->update_source = NULL;
2983 }
2984
2985 if (peer->update_if)
2986 {
2987 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2988 peer->update_if = NULL;
2989 }
2990
2991 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002992 {
2993 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2994 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2995 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2996 }
paul718e3742002-12-13 20:15:29 +00002997 else
2998 BGP_EVENT_ADD (peer, BGP_Stop);
2999 }
3000 return 0;
3001}
3002
3003int
3004peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003005 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003006{
3007 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003008 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003009
3010 /* Adress family must be activated. */
3011 if (! peer->afc[afi][safi])
3012 return BGP_ERR_PEER_INACTIVE;
3013
3014 /* Default originate can't be used for peer group memeber. */
3015 if (peer_is_group_member (peer, afi, safi))
3016 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3017
3018 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3019 || (rmap && ! peer->default_rmap[afi][safi].name)
3020 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3021 {
3022 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3023
3024 if (rmap)
3025 {
3026 if (peer->default_rmap[afi][safi].name)
3027 free (peer->default_rmap[afi][safi].name);
3028 peer->default_rmap[afi][safi].name = strdup (rmap);
3029 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3030 }
3031 }
3032
3033 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3034 {
3035 if (peer->status == Established && peer->afc_nego[afi][safi])
3036 bgp_default_originate (peer, afi, safi, 0);
3037 return 0;
3038 }
3039
3040 /* peer-group member updates. */
3041 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003042 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003043 {
3044 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3045
3046 if (rmap)
3047 {
3048 if (peer->default_rmap[afi][safi].name)
3049 free (peer->default_rmap[afi][safi].name);
3050 peer->default_rmap[afi][safi].name = strdup (rmap);
3051 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3052 }
3053
3054 if (peer->status == Established && peer->afc_nego[afi][safi])
3055 bgp_default_originate (peer, afi, safi, 0);
3056 }
3057 return 0;
3058}
3059
3060int
3061peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3062{
3063 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003064 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003065
3066 /* Adress family must be activated. */
3067 if (! peer->afc[afi][safi])
3068 return BGP_ERR_PEER_INACTIVE;
3069
3070 /* Default originate can't be used for peer group memeber. */
3071 if (peer_is_group_member (peer, afi, safi))
3072 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3073
3074 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3075 {
3076 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3077
3078 if (peer->default_rmap[afi][safi].name)
3079 free (peer->default_rmap[afi][safi].name);
3080 peer->default_rmap[afi][safi].name = NULL;
3081 peer->default_rmap[afi][safi].map = NULL;
3082 }
3083
3084 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3085 {
3086 if (peer->status == Established && peer->afc_nego[afi][safi])
3087 bgp_default_originate (peer, afi, safi, 1);
3088 return 0;
3089 }
3090
3091 /* peer-group member updates. */
3092 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003093 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003094 {
3095 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3096
3097 if (peer->default_rmap[afi][safi].name)
3098 free (peer->default_rmap[afi][safi].name);
3099 peer->default_rmap[afi][safi].name = NULL;
3100 peer->default_rmap[afi][safi].map = NULL;
3101
3102 if (peer->status == Established && peer->afc_nego[afi][safi])
3103 bgp_default_originate (peer, afi, safi, 1);
3104 }
3105 return 0;
3106}
3107
3108int
3109peer_port_set (struct peer *peer, u_int16_t port)
3110{
3111 peer->port = port;
3112 return 0;
3113}
3114
3115int
3116peer_port_unset (struct peer *peer)
3117{
3118 peer->port = BGP_PORT_DEFAULT;
3119 return 0;
3120}
3121
3122/* neighbor weight. */
3123int
3124peer_weight_set (struct peer *peer, u_int16_t weight)
3125{
3126 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003127 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003128
3129 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3130 peer->weight = weight;
3131
3132 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3133 return 0;
3134
3135 /* peer-group member updates. */
3136 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003137 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003138 {
3139 peer->weight = group->conf->weight;
3140 }
3141 return 0;
3142}
3143
3144int
3145peer_weight_unset (struct peer *peer)
3146{
3147 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003148 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003149
3150 /* Set default weight. */
3151 if (peer_group_active (peer))
3152 peer->weight = peer->group->conf->weight;
3153 else
3154 peer->weight = 0;
3155
3156 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3157
3158 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3159 return 0;
3160
3161 /* peer-group member updates. */
3162 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003163 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003164 {
3165 peer->weight = 0;
3166 }
3167 return 0;
3168}
3169
3170int
3171peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3172{
3173 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003174 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003175
3176 /* Not for peer group memeber. */
3177 if (peer_group_active (peer))
3178 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3179
3180 /* keepalive value check. */
3181 if (keepalive > 65535)
3182 return BGP_ERR_INVALID_VALUE;
3183
3184 /* Holdtime value check. */
3185 if (holdtime > 65535)
3186 return BGP_ERR_INVALID_VALUE;
3187
3188 /* Holdtime value must be either 0 or greater than 3. */
3189 if (holdtime < 3 && holdtime != 0)
3190 return BGP_ERR_INVALID_VALUE;
3191
3192 /* Set value to the configuration. */
3193 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3194 peer->holdtime = holdtime;
3195 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3196
3197 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3198 return 0;
3199
3200 /* peer-group member updates. */
3201 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003202 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003203 {
3204 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3205 peer->holdtime = group->conf->holdtime;
3206 peer->keepalive = group->conf->keepalive;
3207 }
3208 return 0;
3209}
3210
3211int
3212peer_timers_unset (struct peer *peer)
3213{
3214 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003215 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003216
3217 if (peer_group_active (peer))
3218 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3219
3220 /* Clear configuration. */
3221 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3222 peer->keepalive = 0;
3223 peer->holdtime = 0;
3224
3225 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3226 return 0;
3227
3228 /* peer-group member updates. */
3229 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003230 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003231 {
3232 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3233 peer->holdtime = 0;
3234 peer->keepalive = 0;
3235 }
3236
3237 return 0;
3238}
3239
3240int
3241peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3242{
3243 if (peer_group_active (peer))
3244 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3245
3246 if (connect > 65535)
3247 return BGP_ERR_INVALID_VALUE;
3248
3249 /* Set value to the configuration. */
3250 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3251 peer->connect = connect;
3252
3253 /* Set value to timer setting. */
3254 peer->v_connect = connect;
3255
3256 return 0;
3257}
3258
3259int
3260peer_timers_connect_unset (struct peer *peer)
3261{
3262 if (peer_group_active (peer))
3263 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3264
3265 /* Clear configuration. */
3266 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3267 peer->connect = 0;
3268
3269 /* Set timer setting to default value. */
3270 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3271
3272 return 0;
3273}
3274
3275int
3276peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3277{
3278 if (peer_group_active (peer))
3279 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3280
3281 if (routeadv > 600)
3282 return BGP_ERR_INVALID_VALUE;
3283
3284 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3285 peer->routeadv = routeadv;
3286 peer->v_routeadv = routeadv;
3287
3288 return 0;
3289}
3290
3291int
3292peer_advertise_interval_unset (struct peer *peer)
3293{
3294 if (peer_group_active (peer))
3295 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3296
3297 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3298 peer->routeadv = 0;
3299
3300 if (peer_sort (peer) == BGP_PEER_IBGP)
3301 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3302 else
3303 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3304
3305 return 0;
3306}
3307
paul718e3742002-12-13 20:15:29 +00003308/* neighbor interface */
3309int
paulfd79ac92004-10-13 05:06:08 +00003310peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003311{
3312 if (peer->ifname)
3313 free (peer->ifname);
3314 peer->ifname = strdup (str);
3315
3316 return 0;
3317}
3318
3319int
3320peer_interface_unset (struct peer *peer)
3321{
3322 if (peer->ifname)
3323 free (peer->ifname);
3324 peer->ifname = NULL;
3325
3326 return 0;
3327}
3328
3329/* Allow-as in. */
3330int
3331peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3332{
3333 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003334 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003335
3336 if (allow_num < 1 || allow_num > 10)
3337 return BGP_ERR_INVALID_VALUE;
3338
3339 if (peer->allowas_in[afi][safi] != allow_num)
3340 {
3341 peer->allowas_in[afi][safi] = allow_num;
3342 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3343 peer_change_action (peer, afi, safi, peer_change_reset_in);
3344 }
3345
3346 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3347 return 0;
3348
3349 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003350 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003351 {
3352 if (peer->allowas_in[afi][safi] != allow_num)
3353 {
3354 peer->allowas_in[afi][safi] = allow_num;
3355 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3356 peer_change_action (peer, afi, safi, peer_change_reset_in);
3357 }
3358
3359 }
3360 return 0;
3361}
3362
3363int
3364peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3365{
3366 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003367 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003368
3369 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3370 {
3371 peer->allowas_in[afi][safi] = 0;
3372 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3373 }
3374
3375 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3376 return 0;
3377
3378 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003379 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003380 {
3381 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3382 {
3383 peer->allowas_in[afi][safi] = 0;
3384 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3385 }
3386 }
3387 return 0;
3388}
3389
3390int
3391peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3392{
3393 struct bgp *bgp = peer->bgp;
3394 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003395 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003396
3397 if (peer_sort (peer) != BGP_PEER_EBGP
3398 && peer_sort (peer) != BGP_PEER_INTERNAL)
3399 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3400
3401 if (bgp->as == as)
3402 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3403
3404 if (peer_group_active (peer))
3405 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3406
3407 if (peer->change_local_as == as &&
3408 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3409 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3410 return 0;
3411
3412 peer->change_local_as = as;
3413 if (no_prepend)
3414 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3415 else
3416 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3417
3418 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3419 {
3420 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003421 {
3422 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3423 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3424 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3425 }
paul718e3742002-12-13 20:15:29 +00003426 else
3427 BGP_EVENT_ADD (peer, BGP_Stop);
3428
3429 return 0;
3430 }
3431
3432 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003433 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003434 {
3435 peer->change_local_as = as;
3436 if (no_prepend)
3437 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3438 else
3439 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3440
3441 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003442 {
3443 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3444 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3445 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3446 }
paul718e3742002-12-13 20:15:29 +00003447 else
3448 BGP_EVENT_ADD (peer, BGP_Stop);
3449 }
3450
3451 return 0;
3452}
3453
3454int
3455peer_local_as_unset (struct peer *peer)
3456{
3457 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003458 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003459
3460 if (peer_group_active (peer))
3461 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3462
3463 if (! peer->change_local_as)
3464 return 0;
3465
3466 peer->change_local_as = 0;
3467 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3468
3469 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3470 {
3471 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003472 {
3473 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3474 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3475 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3476 }
paul718e3742002-12-13 20:15:29 +00003477 else
3478 BGP_EVENT_ADD (peer, BGP_Stop);
3479
3480 return 0;
3481 }
3482
3483 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003484 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003485 {
3486 peer->change_local_as = 0;
3487 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3488
3489 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003490 {
3491 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3492 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3493 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3494 }
paul718e3742002-12-13 20:15:29 +00003495 else
3496 BGP_EVENT_ADD (peer, BGP_Stop);
3497 }
3498 return 0;
3499}
3500
Paul Jakma0df7c912008-07-21 21:02:49 +00003501/* Set password for authenticating with the peer. */
3502int
3503peer_password_set (struct peer *peer, const char *password)
3504{
3505 struct listnode *nn, *nnode;
3506 int len = password ? strlen(password) : 0;
3507 int ret = BGP_SUCCESS;
3508
3509 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3510 return BGP_ERR_INVALID_VALUE;
3511
3512 if (peer->password && strcmp (peer->password, password) == 0
3513 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3514 return 0;
3515
3516 if (peer->password)
3517 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3518
3519 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3520
3521 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3522 {
3523 if (peer->status == Established)
3524 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3525 else
3526 BGP_EVENT_ADD (peer, BGP_Stop);
3527
3528 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3529 }
3530
3531 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3532 {
3533 if (peer->password && strcmp (peer->password, password) == 0)
3534 continue;
3535
3536 if (peer->password)
3537 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3538
3539 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3540
3541 if (peer->status == Established)
3542 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3543 else
3544 BGP_EVENT_ADD (peer, BGP_Stop);
3545
3546 if (bgp_md5_set (peer) < 0)
3547 ret = BGP_ERR_TCPSIG_FAILED;
3548 }
3549
3550 return ret;
3551}
3552
3553int
3554peer_password_unset (struct peer *peer)
3555{
3556 struct listnode *nn, *nnode;
3557
3558 if (!peer->password
3559 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3560 return 0;
3561
3562 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3563 {
3564 if (peer_group_active (peer)
3565 && peer->group->conf->password
3566 && strcmp (peer->group->conf->password, peer->password) == 0)
3567 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3568
3569 if (peer->status == Established)
3570 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3571 else
3572 BGP_EVENT_ADD (peer, BGP_Stop);
3573
3574 if (peer->password)
3575 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3576
3577 peer->password = NULL;
3578
3579 bgp_md5_set (peer);
3580
3581 return 0;
3582 }
3583
3584 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3585 peer->password = NULL;
3586
3587 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3588 {
3589 if (!peer->password)
3590 continue;
3591
3592 if (peer->status == Established)
3593 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3594 else
3595 BGP_EVENT_ADD (peer, BGP_Stop);
3596
3597 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3598 peer->password = NULL;
3599
3600 bgp_md5_set (peer);
3601 }
3602
3603 return 0;
3604}
3605
paul718e3742002-12-13 20:15:29 +00003606/* Set distribute list to the peer. */
3607int
3608peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003609 const char *name)
paul718e3742002-12-13 20:15:29 +00003610{
3611 struct bgp_filter *filter;
3612 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003613 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003614
3615 if (! peer->afc[afi][safi])
3616 return BGP_ERR_PEER_INACTIVE;
3617
3618 if (direct != FILTER_IN && direct != FILTER_OUT)
3619 return BGP_ERR_INVALID_VALUE;
3620
3621 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3622 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3623
3624 filter = &peer->filter[afi][safi];
3625
3626 if (filter->plist[direct].name)
3627 return BGP_ERR_PEER_FILTER_CONFLICT;
3628
3629 if (filter->dlist[direct].name)
3630 free (filter->dlist[direct].name);
3631 filter->dlist[direct].name = strdup (name);
3632 filter->dlist[direct].alist = access_list_lookup (afi, name);
3633
3634 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3635 return 0;
3636
3637 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003638 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003639 {
3640 filter = &peer->filter[afi][safi];
3641
3642 if (! peer->af_group[afi][safi])
3643 continue;
3644
3645 if (filter->dlist[direct].name)
3646 free (filter->dlist[direct].name);
3647 filter->dlist[direct].name = strdup (name);
3648 filter->dlist[direct].alist = access_list_lookup (afi, name);
3649 }
3650
3651 return 0;
3652}
3653
3654int
3655peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3656{
3657 struct bgp_filter *filter;
3658 struct bgp_filter *gfilter;
3659 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003660 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003661
3662 if (! peer->afc[afi][safi])
3663 return BGP_ERR_PEER_INACTIVE;
3664
3665 if (direct != FILTER_IN && direct != FILTER_OUT)
3666 return BGP_ERR_INVALID_VALUE;
3667
3668 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3669 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3670
3671 filter = &peer->filter[afi][safi];
3672
3673 /* apply peer-group filter */
3674 if (peer->af_group[afi][safi])
3675 {
3676 gfilter = &peer->group->conf->filter[afi][safi];
3677
3678 if (gfilter->dlist[direct].name)
3679 {
3680 if (filter->dlist[direct].name)
3681 free (filter->dlist[direct].name);
3682 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3683 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3684 return 0;
3685 }
3686 }
3687
3688 if (filter->dlist[direct].name)
3689 free (filter->dlist[direct].name);
3690 filter->dlist[direct].name = NULL;
3691 filter->dlist[direct].alist = NULL;
3692
3693 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3694 return 0;
3695
3696 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003697 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003698 {
3699 filter = &peer->filter[afi][safi];
3700
3701 if (! peer->af_group[afi][safi])
3702 continue;
3703
3704 if (filter->dlist[direct].name)
3705 free (filter->dlist[direct].name);
3706 filter->dlist[direct].name = NULL;
3707 filter->dlist[direct].alist = NULL;
3708 }
3709
3710 return 0;
3711}
3712
3713/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003714static void
paul718e3742002-12-13 20:15:29 +00003715peer_distribute_update (struct access_list *access)
3716{
3717 afi_t afi;
3718 safi_t safi;
3719 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003720 struct listnode *mnode, *mnnode;
3721 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003722 struct bgp *bgp;
3723 struct peer *peer;
3724 struct peer_group *group;
3725 struct bgp_filter *filter;
3726
paul1eb8ef22005-04-07 07:30:20 +00003727 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003728 {
paul1eb8ef22005-04-07 07:30:20 +00003729 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003730 {
3731 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3732 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3733 {
3734 filter = &peer->filter[afi][safi];
3735
3736 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3737 {
3738 if (filter->dlist[direct].name)
3739 filter->dlist[direct].alist =
3740 access_list_lookup (afi, filter->dlist[direct].name);
3741 else
3742 filter->dlist[direct].alist = NULL;
3743 }
3744 }
3745 }
paul1eb8ef22005-04-07 07:30:20 +00003746 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003747 {
3748 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3749 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3750 {
3751 filter = &group->conf->filter[afi][safi];
3752
3753 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3754 {
3755 if (filter->dlist[direct].name)
3756 filter->dlist[direct].alist =
3757 access_list_lookup (afi, filter->dlist[direct].name);
3758 else
3759 filter->dlist[direct].alist = NULL;
3760 }
3761 }
3762 }
3763 }
3764}
3765
3766/* Set prefix list to the peer. */
3767int
3768peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003769 const char *name)
paul718e3742002-12-13 20:15:29 +00003770{
3771 struct bgp_filter *filter;
3772 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003773 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003774
3775 if (! peer->afc[afi][safi])
3776 return BGP_ERR_PEER_INACTIVE;
3777
3778 if (direct != FILTER_IN && direct != FILTER_OUT)
3779 return BGP_ERR_INVALID_VALUE;
3780
3781 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3782 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3783
3784 filter = &peer->filter[afi][safi];
3785
3786 if (filter->dlist[direct].name)
3787 return BGP_ERR_PEER_FILTER_CONFLICT;
3788
3789 if (filter->plist[direct].name)
3790 free (filter->plist[direct].name);
3791 filter->plist[direct].name = strdup (name);
3792 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3793
3794 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3795 return 0;
3796
3797 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003798 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003799 {
3800 filter = &peer->filter[afi][safi];
3801
3802 if (! peer->af_group[afi][safi])
3803 continue;
3804
3805 if (filter->plist[direct].name)
3806 free (filter->plist[direct].name);
3807 filter->plist[direct].name = strdup (name);
3808 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3809 }
3810 return 0;
3811}
3812
3813int
3814peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3815{
3816 struct bgp_filter *filter;
3817 struct bgp_filter *gfilter;
3818 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003819 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003820
3821 if (! peer->afc[afi][safi])
3822 return BGP_ERR_PEER_INACTIVE;
3823
3824 if (direct != FILTER_IN && direct != FILTER_OUT)
3825 return BGP_ERR_INVALID_VALUE;
3826
3827 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3828 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3829
3830 filter = &peer->filter[afi][safi];
3831
3832 /* apply peer-group filter */
3833 if (peer->af_group[afi][safi])
3834 {
3835 gfilter = &peer->group->conf->filter[afi][safi];
3836
3837 if (gfilter->plist[direct].name)
3838 {
3839 if (filter->plist[direct].name)
3840 free (filter->plist[direct].name);
3841 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3842 filter->plist[direct].plist = gfilter->plist[direct].plist;
3843 return 0;
3844 }
3845 }
3846
3847 if (filter->plist[direct].name)
3848 free (filter->plist[direct].name);
3849 filter->plist[direct].name = NULL;
3850 filter->plist[direct].plist = NULL;
3851
3852 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3853 return 0;
3854
3855 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003856 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003857 {
3858 filter = &peer->filter[afi][safi];
3859
3860 if (! peer->af_group[afi][safi])
3861 continue;
3862
3863 if (filter->plist[direct].name)
3864 free (filter->plist[direct].name);
3865 filter->plist[direct].name = NULL;
3866 filter->plist[direct].plist = NULL;
3867 }
3868
3869 return 0;
3870}
3871
3872/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003873static void
paul718e3742002-12-13 20:15:29 +00003874peer_prefix_list_update (struct prefix_list *plist)
3875{
paul1eb8ef22005-04-07 07:30:20 +00003876 struct listnode *mnode, *mnnode;
3877 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003878 struct bgp *bgp;
3879 struct peer *peer;
3880 struct peer_group *group;
3881 struct bgp_filter *filter;
3882 afi_t afi;
3883 safi_t safi;
3884 int direct;
3885
paul1eb8ef22005-04-07 07:30:20 +00003886 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003887 {
paul1eb8ef22005-04-07 07:30:20 +00003888 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003889 {
3890 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3891 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3892 {
3893 filter = &peer->filter[afi][safi];
3894
3895 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3896 {
3897 if (filter->plist[direct].name)
3898 filter->plist[direct].plist =
3899 prefix_list_lookup (afi, filter->plist[direct].name);
3900 else
3901 filter->plist[direct].plist = NULL;
3902 }
3903 }
3904 }
paul1eb8ef22005-04-07 07:30:20 +00003905 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003906 {
3907 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3908 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3909 {
3910 filter = &group->conf->filter[afi][safi];
3911
3912 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3913 {
3914 if (filter->plist[direct].name)
3915 filter->plist[direct].plist =
3916 prefix_list_lookup (afi, filter->plist[direct].name);
3917 else
3918 filter->plist[direct].plist = NULL;
3919 }
3920 }
3921 }
3922 }
3923}
3924
3925int
3926peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003927 const char *name)
paul718e3742002-12-13 20:15:29 +00003928{
3929 struct bgp_filter *filter;
3930 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003931 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003932
3933 if (! peer->afc[afi][safi])
3934 return BGP_ERR_PEER_INACTIVE;
3935
3936 if (direct != FILTER_IN && direct != FILTER_OUT)
3937 return BGP_ERR_INVALID_VALUE;
3938
3939 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3940 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3941
3942 filter = &peer->filter[afi][safi];
3943
3944 if (filter->aslist[direct].name)
3945 free (filter->aslist[direct].name);
3946 filter->aslist[direct].name = strdup (name);
3947 filter->aslist[direct].aslist = as_list_lookup (name);
3948
3949 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3950 return 0;
3951
3952 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003953 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003954 {
3955 filter = &peer->filter[afi][safi];
3956
3957 if (! peer->af_group[afi][safi])
3958 continue;
3959
3960 if (filter->aslist[direct].name)
3961 free (filter->aslist[direct].name);
3962 filter->aslist[direct].name = strdup (name);
3963 filter->aslist[direct].aslist = as_list_lookup (name);
3964 }
3965 return 0;
3966}
3967
3968int
3969peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3970{
3971 struct bgp_filter *filter;
3972 struct bgp_filter *gfilter;
3973 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003974 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003975
3976 if (! peer->afc[afi][safi])
3977 return BGP_ERR_PEER_INACTIVE;
3978
hassob5f29602005-05-25 21:00:28 +00003979 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003980 return BGP_ERR_INVALID_VALUE;
3981
hassob5f29602005-05-25 21:00:28 +00003982 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003983 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3984
3985 filter = &peer->filter[afi][safi];
3986
3987 /* apply peer-group filter */
3988 if (peer->af_group[afi][safi])
3989 {
3990 gfilter = &peer->group->conf->filter[afi][safi];
3991
3992 if (gfilter->aslist[direct].name)
3993 {
3994 if (filter->aslist[direct].name)
3995 free (filter->aslist[direct].name);
3996 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3997 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3998 return 0;
3999 }
4000 }
4001
4002 if (filter->aslist[direct].name)
4003 free (filter->aslist[direct].name);
4004 filter->aslist[direct].name = NULL;
4005 filter->aslist[direct].aslist = NULL;
4006
4007 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4008 return 0;
4009
4010 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004011 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004012 {
4013 filter = &peer->filter[afi][safi];
4014
4015 if (! peer->af_group[afi][safi])
4016 continue;
4017
4018 if (filter->aslist[direct].name)
4019 free (filter->aslist[direct].name);
4020 filter->aslist[direct].name = NULL;
4021 filter->aslist[direct].aslist = NULL;
4022 }
4023
4024 return 0;
4025}
4026
paul94f2b392005-06-28 12:44:16 +00004027static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004028peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004029{
4030 afi_t afi;
4031 safi_t safi;
4032 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004033 struct listnode *mnode, *mnnode;
4034 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004035 struct bgp *bgp;
4036 struct peer *peer;
4037 struct peer_group *group;
4038 struct bgp_filter *filter;
4039
paul1eb8ef22005-04-07 07:30:20 +00004040 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004041 {
paul1eb8ef22005-04-07 07:30:20 +00004042 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004043 {
4044 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4045 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4046 {
4047 filter = &peer->filter[afi][safi];
4048
4049 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4050 {
4051 if (filter->aslist[direct].name)
4052 filter->aslist[direct].aslist =
4053 as_list_lookup (filter->aslist[direct].name);
4054 else
4055 filter->aslist[direct].aslist = NULL;
4056 }
4057 }
4058 }
paul1eb8ef22005-04-07 07:30:20 +00004059 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004060 {
4061 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4062 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4063 {
4064 filter = &group->conf->filter[afi][safi];
4065
4066 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4067 {
4068 if (filter->aslist[direct].name)
4069 filter->aslist[direct].aslist =
4070 as_list_lookup (filter->aslist[direct].name);
4071 else
4072 filter->aslist[direct].aslist = NULL;
4073 }
4074 }
4075 }
4076 }
4077}
4078
4079/* Set route-map to the peer. */
4080int
4081peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004082 const char *name)
paul718e3742002-12-13 20:15:29 +00004083{
4084 struct bgp_filter *filter;
4085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004086 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004087
4088 if (! peer->afc[afi][safi])
4089 return BGP_ERR_PEER_INACTIVE;
4090
paulfee0f4c2004-09-13 05:12:46 +00004091 if (direct != RMAP_IN && direct != RMAP_OUT &&
4092 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004093 return BGP_ERR_INVALID_VALUE;
4094
paulfee0f4c2004-09-13 05:12:46 +00004095 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4096 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004097 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4098
4099 filter = &peer->filter[afi][safi];
4100
4101 if (filter->map[direct].name)
4102 free (filter->map[direct].name);
4103
4104 filter->map[direct].name = strdup (name);
4105 filter->map[direct].map = route_map_lookup_by_name (name);
4106
4107 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4108 return 0;
4109
4110 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004112 {
4113 filter = &peer->filter[afi][safi];
4114
4115 if (! peer->af_group[afi][safi])
4116 continue;
4117
4118 if (filter->map[direct].name)
4119 free (filter->map[direct].name);
4120 filter->map[direct].name = strdup (name);
4121 filter->map[direct].map = route_map_lookup_by_name (name);
4122 }
4123 return 0;
4124}
4125
4126/* Unset route-map from the peer. */
4127int
4128peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4129{
4130 struct bgp_filter *filter;
4131 struct bgp_filter *gfilter;
4132 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004133 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004134
4135 if (! peer->afc[afi][safi])
4136 return BGP_ERR_PEER_INACTIVE;
4137
hassob5f29602005-05-25 21:00:28 +00004138 if (direct != RMAP_IN && direct != RMAP_OUT &&
4139 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004140 return BGP_ERR_INVALID_VALUE;
4141
hassob5f29602005-05-25 21:00:28 +00004142 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4143 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004144 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4145
4146 filter = &peer->filter[afi][safi];
4147
4148 /* apply peer-group filter */
4149 if (peer->af_group[afi][safi])
4150 {
4151 gfilter = &peer->group->conf->filter[afi][safi];
4152
4153 if (gfilter->map[direct].name)
4154 {
4155 if (filter->map[direct].name)
4156 free (filter->map[direct].name);
4157 filter->map[direct].name = strdup (gfilter->map[direct].name);
4158 filter->map[direct].map = gfilter->map[direct].map;
4159 return 0;
4160 }
4161 }
4162
4163 if (filter->map[direct].name)
4164 free (filter->map[direct].name);
4165 filter->map[direct].name = NULL;
4166 filter->map[direct].map = NULL;
4167
4168 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4169 return 0;
4170
4171 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004172 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004173 {
4174 filter = &peer->filter[afi][safi];
4175
4176 if (! peer->af_group[afi][safi])
4177 continue;
4178
4179 if (filter->map[direct].name)
4180 free (filter->map[direct].name);
4181 filter->map[direct].name = NULL;
4182 filter->map[direct].map = NULL;
4183 }
4184 return 0;
4185}
4186
4187/* Set unsuppress-map to the peer. */
4188int
paulfd79ac92004-10-13 05:06:08 +00004189peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4190 const char *name)
paul718e3742002-12-13 20:15:29 +00004191{
4192 struct bgp_filter *filter;
4193 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004194 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004195
4196 if (! peer->afc[afi][safi])
4197 return BGP_ERR_PEER_INACTIVE;
4198
4199 if (peer_is_group_member (peer, afi, safi))
4200 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4201
4202 filter = &peer->filter[afi][safi];
4203
4204 if (filter->usmap.name)
4205 free (filter->usmap.name);
4206
4207 filter->usmap.name = strdup (name);
4208 filter->usmap.map = route_map_lookup_by_name (name);
4209
4210 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4211 return 0;
4212
4213 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004214 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004215 {
4216 filter = &peer->filter[afi][safi];
4217
4218 if (! peer->af_group[afi][safi])
4219 continue;
4220
4221 if (filter->usmap.name)
4222 free (filter->usmap.name);
4223 filter->usmap.name = strdup (name);
4224 filter->usmap.map = route_map_lookup_by_name (name);
4225 }
4226 return 0;
4227}
4228
4229/* Unset route-map from the peer. */
4230int
4231peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4232{
4233 struct bgp_filter *filter;
4234 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004235 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004236
4237 if (! peer->afc[afi][safi])
4238 return BGP_ERR_PEER_INACTIVE;
4239
4240 if (peer_is_group_member (peer, afi, safi))
4241 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4242
4243 filter = &peer->filter[afi][safi];
4244
4245 if (filter->usmap.name)
4246 free (filter->usmap.name);
4247 filter->usmap.name = NULL;
4248 filter->usmap.map = NULL;
4249
4250 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4251 return 0;
4252
4253 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004254 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004255 {
4256 filter = &peer->filter[afi][safi];
4257
4258 if (! peer->af_group[afi][safi])
4259 continue;
4260
4261 if (filter->usmap.name)
4262 free (filter->usmap.name);
4263 filter->usmap.name = NULL;
4264 filter->usmap.map = NULL;
4265 }
4266 return 0;
4267}
4268
4269int
4270peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004271 u_int32_t max, u_char threshold,
4272 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004273{
4274 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004275 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004276
4277 if (! peer->afc[afi][safi])
4278 return BGP_ERR_PEER_INACTIVE;
4279
4280 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4281 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004282 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004283 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004284 if (warning)
4285 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4286 else
4287 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4288
4289 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4290 return 0;
4291
4292 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004293 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004294 {
4295 if (! peer->af_group[afi][safi])
4296 continue;
4297
4298 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4299 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004300 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004301 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004302 if (warning)
4303 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4304 else
4305 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4306 }
4307 return 0;
4308}
4309
4310int
4311peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4312{
4313 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004314 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004315
4316 if (! peer->afc[afi][safi])
4317 return BGP_ERR_PEER_INACTIVE;
4318
4319 /* apply peer-group config */
4320 if (peer->af_group[afi][safi])
4321 {
4322 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4323 PEER_FLAG_MAX_PREFIX))
4324 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4325 else
4326 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4327
4328 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4329 PEER_FLAG_MAX_PREFIX_WARNING))
4330 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4331 else
4332 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4333
4334 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004335 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004336 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004337 return 0;
4338 }
4339
4340 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4341 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4342 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004343 peer->pmax_threshold[afi][safi] = 0;
4344 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004345
4346 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4347 return 0;
4348
4349 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004350 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004351 {
4352 if (! peer->af_group[afi][safi])
4353 continue;
4354
4355 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4356 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4357 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004358 peer->pmax_threshold[afi][safi] = 0;
4359 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004360 }
4361 return 0;
4362}
4363
Nick Hilliardfa411a22011-03-23 15:33:17 +00004364/* Set # of hops between us and BGP peer. */
4365int
4366peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4367{
4368 struct peer_group *group;
4369 struct listnode *node, *nnode;
4370 struct peer *peer1;
4371 int ret;
4372
4373 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4374
4375 if (peer_sort (peer) == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004376 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004377
4378 /* We cannot configure ttl-security hops when ebgp-multihop is already
4379 set. For non peer-groups, the check is simple. For peer-groups, it's
4380 slightly messy, because we need to check both the peer-group structure
4381 and all peer-group members for any trace of ebgp-multihop configuration
4382 before actually applying the ttl-security rules. Cisco really made a
4383 mess of this configuration parameter, and OpenBGPD got it right.
4384 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004385
4386 if (peer->gtsm_hops == 0) {
4387 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4388 {
4389 group = peer->group;
4390 if (group->conf->ttl != 1)
4391 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004392
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004393 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4394 {
4395 if (peer_sort (peer1) == BGP_PEER_IBGP)
4396 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004397
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004398 if (peer1->ttl != 1)
4399 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4400 }
4401 }
4402 else
4403 {
4404 if (peer->ttl != 1)
4405 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4406 }
4407 /* specify MAXTTL on outgoing packets */
4408 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4409 if (ret != 0)
4410 return ret;
4411 }
4412
Nick Hilliardfa411a22011-03-23 15:33:17 +00004413 peer->gtsm_hops = gtsm_hops;
4414
Nick Hilliardfa411a22011-03-23 15:33:17 +00004415 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4416 {
4417 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4418 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4419 }
4420 else
4421 {
4422 group = peer->group;
4423 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4424 {
4425 if (peer_sort (peer) == BGP_PEER_IBGP)
4426 continue;
4427
4428 peer->gtsm_hops = group->conf->gtsm_hops;
4429
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004430 /* Change setting of existing peer
4431 * established then change value (may break connectivity)
4432 * not established yet (teardown session and restart)
4433 * no session then do nothing (will get handled by next connection)
4434 */
4435 if (peer->status == Established)
4436 {
4437 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4438 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4439 MAXTTL + 1 - peer->gtsm_hops);
4440 }
4441 else if (peer->status < Established)
4442 {
4443 if (BGP_DEBUG (events, EVENTS))
4444 zlog_debug ("%s Min-ttl changed", peer->host);
4445 BGP_EVENT_ADD (peer, BGP_Stop);
4446 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004447 }
4448 }
4449
4450 return 0;
4451}
4452
4453int
4454peer_ttl_security_hops_unset (struct peer *peer)
4455{
4456 struct peer_group *group;
4457 struct listnode *node, *nnode;
4458 struct peer *opeer;
4459
4460 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4461
4462 if (peer_sort (peer) == BGP_PEER_IBGP)
4463 return 0;
4464
4465 /* if a peer-group member, then reset to peer-group default rather than 0 */
4466 if (peer_group_active (peer))
4467 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4468 else
4469 peer->gtsm_hops = 0;
4470
4471 opeer = peer;
4472 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4473 {
4474 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4475 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4476 }
4477 else
4478 {
4479 group = peer->group;
4480 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4481 {
4482 if (peer_sort (peer) == BGP_PEER_IBGP)
4483 continue;
4484
4485 peer->gtsm_hops = 0;
4486
4487 if (peer->fd >= 0)
4488 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4489 }
4490 }
4491
4492 return peer_ebgp_multihop_unset (opeer);
4493}
4494
paul718e3742002-12-13 20:15:29 +00004495int
4496peer_clear (struct peer *peer)
4497{
4498 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4499 {
hasso0a486e52005-02-01 20:57:17 +00004500 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4501 {
4502 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4503 if (peer->t_pmax_restart)
4504 {
4505 BGP_TIMER_OFF (peer->t_pmax_restart);
4506 if (BGP_DEBUG (events, EVENTS))
4507 zlog_debug ("%s Maximum-prefix restart timer canceled",
4508 peer->host);
4509 }
4510 BGP_EVENT_ADD (peer, BGP_Start);
4511 return 0;
4512 }
4513
paul718e3742002-12-13 20:15:29 +00004514 peer->v_start = BGP_INIT_START_TIMER;
4515 if (peer->status == Established)
4516 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4517 BGP_NOTIFY_CEASE_ADMIN_RESET);
4518 else
4519 BGP_EVENT_ADD (peer, BGP_Stop);
4520 }
4521 return 0;
4522}
4523
4524int
4525peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4526 enum bgp_clear_type stype)
4527{
4528 if (peer->status != Established)
4529 return 0;
4530
4531 if (! peer->afc[afi][safi])
4532 return BGP_ERR_AF_UNCONFIGURED;
4533
paulfee0f4c2004-09-13 05:12:46 +00004534 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4535 {
4536 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4537 return 0;
4538 bgp_check_local_routes_rsclient (peer, afi, safi);
4539 bgp_soft_reconfig_rsclient (peer, afi, safi);
4540 }
4541
paul718e3742002-12-13 20:15:29 +00004542 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4543 bgp_announce_route (peer, afi, safi);
4544
4545 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4546 {
4547 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4548 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4549 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4550 {
4551 struct bgp_filter *filter = &peer->filter[afi][safi];
4552 u_char prefix_type;
4553
4554 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4555 prefix_type = ORF_TYPE_PREFIX;
4556 else
4557 prefix_type = ORF_TYPE_PREFIX_OLD;
4558
4559 if (filter->plist[FILTER_IN].plist)
4560 {
4561 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4562 bgp_route_refresh_send (peer, afi, safi,
4563 prefix_type, REFRESH_DEFER, 1);
4564 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4565 REFRESH_IMMEDIATE, 0);
4566 }
4567 else
4568 {
4569 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4570 bgp_route_refresh_send (peer, afi, safi,
4571 prefix_type, REFRESH_IMMEDIATE, 1);
4572 else
4573 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4574 }
4575 return 0;
4576 }
4577 }
4578
4579 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4580 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4581 {
4582 /* If neighbor has soft reconfiguration inbound flag.
4583 Use Adj-RIB-In database. */
4584 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4585 bgp_soft_reconfig_in (peer, afi, safi);
4586 else
4587 {
4588 /* If neighbor has route refresh capability, send route refresh
4589 message to the peer. */
4590 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4591 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4592 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4593 else
4594 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4595 }
4596 }
4597 return 0;
4598}
4599
paulfd79ac92004-10-13 05:06:08 +00004600/* Display peer uptime.*/
4601/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004602char *
4603peer_uptime (time_t uptime2, char *buf, size_t len)
4604{
4605 time_t uptime1;
4606 struct tm *tm;
4607
4608 /* Check buffer length. */
4609 if (len < BGP_UPTIME_LEN)
4610 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004611 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004612 /* XXX: should return status instead of buf... */
4613 snprintf (buf, len, "<error> ");
4614 return buf;
paul718e3742002-12-13 20:15:29 +00004615 }
4616
4617 /* If there is no connection has been done before print `never'. */
4618 if (uptime2 == 0)
4619 {
4620 snprintf (buf, len, "never ");
4621 return buf;
4622 }
4623
4624 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004625 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004626 uptime1 -= uptime2;
4627 tm = gmtime (&uptime1);
4628
4629 /* Making formatted timer strings. */
4630#define ONE_DAY_SECOND 60*60*24
4631#define ONE_WEEK_SECOND 60*60*24*7
4632
4633 if (uptime1 < ONE_DAY_SECOND)
4634 snprintf (buf, len, "%02d:%02d:%02d",
4635 tm->tm_hour, tm->tm_min, tm->tm_sec);
4636 else if (uptime1 < ONE_WEEK_SECOND)
4637 snprintf (buf, len, "%dd%02dh%02dm",
4638 tm->tm_yday, tm->tm_hour, tm->tm_min);
4639 else
4640 snprintf (buf, len, "%02dw%dd%02dh",
4641 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4642 return buf;
4643}
4644
paul94f2b392005-06-28 12:44:16 +00004645static void
paul718e3742002-12-13 20:15:29 +00004646bgp_config_write_filter (struct vty *vty, struct peer *peer,
4647 afi_t afi, safi_t safi)
4648{
4649 struct bgp_filter *filter;
4650 struct bgp_filter *gfilter = NULL;
4651 char *addr;
4652 int in = FILTER_IN;
4653 int out = FILTER_OUT;
4654
4655 addr = peer->host;
4656 filter = &peer->filter[afi][safi];
4657 if (peer->af_group[afi][safi])
4658 gfilter = &peer->group->conf->filter[afi][safi];
4659
4660 /* distribute-list. */
4661 if (filter->dlist[in].name)
4662 if (! gfilter || ! gfilter->dlist[in].name
4663 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4664 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4665 filter->dlist[in].name, VTY_NEWLINE);
4666 if (filter->dlist[out].name && ! gfilter)
4667 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4668 filter->dlist[out].name, VTY_NEWLINE);
4669
4670 /* prefix-list. */
4671 if (filter->plist[in].name)
4672 if (! gfilter || ! gfilter->plist[in].name
4673 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4674 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4675 filter->plist[in].name, VTY_NEWLINE);
4676 if (filter->plist[out].name && ! gfilter)
4677 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4678 filter->plist[out].name, VTY_NEWLINE);
4679
4680 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004681 if (filter->map[RMAP_IN].name)
4682 if (! gfilter || ! gfilter->map[RMAP_IN].name
4683 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004684 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004685 filter->map[RMAP_IN].name, VTY_NEWLINE);
4686 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004687 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004688 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4689 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4690 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4691 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4692 if (filter->map[RMAP_EXPORT].name)
4693 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4694 || strcmp (filter->map[RMAP_EXPORT].name,
4695 gfilter->map[RMAP_EXPORT].name) != 0)
4696 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4697 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004698
4699 /* unsuppress-map */
4700 if (filter->usmap.name && ! gfilter)
4701 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4702 filter->usmap.name, VTY_NEWLINE);
4703
4704 /* filter-list. */
4705 if (filter->aslist[in].name)
4706 if (! gfilter || ! gfilter->aslist[in].name
4707 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4708 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4709 filter->aslist[in].name, VTY_NEWLINE);
4710 if (filter->aslist[out].name && ! gfilter)
4711 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4712 filter->aslist[out].name, VTY_NEWLINE);
4713}
4714
4715/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004716static void
paul718e3742002-12-13 20:15:29 +00004717bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4718 struct peer *peer, afi_t afi, safi_t safi)
4719{
paul718e3742002-12-13 20:15:29 +00004720 struct peer *g_peer = NULL;
4721 char buf[SU_ADDRSTRLEN];
4722 char *addr;
4723
paul718e3742002-12-13 20:15:29 +00004724 addr = peer->host;
4725 if (peer_group_active (peer))
4726 g_peer = peer->group->conf;
4727
4728 /************************************
4729 ****** Global to the neighbor ******
4730 ************************************/
4731 if (afi == AFI_IP && safi == SAFI_UNICAST)
4732 {
4733 /* remote-as. */
4734 if (! peer_group_active (peer))
4735 {
4736 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4737 vty_out (vty, " neighbor %s peer-group%s", addr,
4738 VTY_NEWLINE);
4739 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004740 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004741 VTY_NEWLINE);
4742 }
4743 else
4744 {
4745 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004746 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004747 VTY_NEWLINE);
4748 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4749 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4750 peer->group->name, VTY_NEWLINE);
4751 }
4752
4753 /* local-as. */
4754 if (peer->change_local_as)
4755 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004756 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004757 peer->change_local_as,
4758 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4759 " no-prepend" : "", VTY_NEWLINE);
4760
4761 /* Description. */
4762 if (peer->desc)
4763 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4764 VTY_NEWLINE);
4765
4766 /* Shutdown. */
4767 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4768 if (! peer_group_active (peer) ||
4769 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4770 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4771
Paul Jakma0df7c912008-07-21 21:02:49 +00004772 /* Password. */
4773 if (peer->password)
4774 if (!peer_group_active (peer)
4775 || ! g_peer->password
4776 || strcmp (peer->password, g_peer->password) != 0)
4777 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4778 VTY_NEWLINE);
4779
paul718e3742002-12-13 20:15:29 +00004780 /* BGP port. */
4781 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004782 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004783 VTY_NEWLINE);
4784
4785 /* Local interface name. */
4786 if (peer->ifname)
4787 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4788 VTY_NEWLINE);
4789
4790 /* Passive. */
4791 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4792 if (! peer_group_active (peer) ||
4793 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4794 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4795
4796 /* EBGP multihop. */
Nick Hilliardfa411a22011-03-23 15:33:17 +00004797 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
4798 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004799 if (! peer_group_active (peer) ||
4800 g_peer->ttl != peer->ttl)
4801 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4802 VTY_NEWLINE);
4803
Nick Hilliardfa411a22011-03-23 15:33:17 +00004804 /* ttl-security hops */
4805 if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
4806 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004807 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004808 peer->gtsm_hops, VTY_NEWLINE);
4809
hasso6ffd2072005-02-02 14:50:11 +00004810 /* disable-connected-check. */
4811 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004812 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004813 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4814 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004815
4816 /* Update-source. */
4817 if (peer->update_if)
4818 if (! peer_group_active (peer) || ! g_peer->update_if
4819 || strcmp (g_peer->update_if, peer->update_if) != 0)
4820 vty_out (vty, " neighbor %s update-source %s%s", addr,
4821 peer->update_if, VTY_NEWLINE);
4822 if (peer->update_source)
4823 if (! peer_group_active (peer) || ! g_peer->update_source
4824 || sockunion_cmp (g_peer->update_source,
4825 peer->update_source) != 0)
4826 vty_out (vty, " neighbor %s update-source %s%s", addr,
4827 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4828 VTY_NEWLINE);
4829
paul718e3742002-12-13 20:15:29 +00004830 /* advertisement-interval */
4831 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4832 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4833 addr, peer->v_routeadv, VTY_NEWLINE);
4834
4835 /* timers. */
4836 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4837 && ! peer_group_active (peer))
4838 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4839 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4840
4841 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4842 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4843 peer->connect, VTY_NEWLINE);
4844
4845 /* Default weight. */
4846 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4847 if (! peer_group_active (peer) ||
4848 g_peer->weight != peer->weight)
4849 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4850 VTY_NEWLINE);
4851
paul718e3742002-12-13 20:15:29 +00004852 /* Dynamic capability. */
4853 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4854 if (! peer_group_active (peer) ||
4855 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4856 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4857 VTY_NEWLINE);
4858
4859 /* dont capability negotiation. */
4860 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4861 if (! peer_group_active (peer) ||
4862 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4863 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4864 VTY_NEWLINE);
4865
4866 /* override capability negotiation. */
4867 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4868 if (! peer_group_active (peer) ||
4869 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4870 vty_out (vty, " neighbor %s override-capability%s", addr,
4871 VTY_NEWLINE);
4872
4873 /* strict capability negotiation. */
4874 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4875 if (! peer_group_active (peer) ||
4876 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4877 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4878 VTY_NEWLINE);
4879
4880 if (! peer_group_active (peer))
4881 {
4882 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4883 {
4884 if (peer->afc[AFI_IP][SAFI_UNICAST])
4885 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4886 }
4887 else
4888 {
4889 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4890 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4891 }
4892 }
4893 }
4894
4895
4896 /************************************
4897 ****** Per AF to the neighbor ******
4898 ************************************/
4899
4900 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4901 {
4902 if (peer->af_group[afi][safi])
4903 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4904 peer->group->name, VTY_NEWLINE);
4905 else
4906 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4907 }
4908
4909 /* ORF capability. */
4910 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4911 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4912 if (! peer->af_group[afi][safi])
4913 {
4914 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4915
4916 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4917 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4918 vty_out (vty, " both");
4919 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4920 vty_out (vty, " send");
4921 else
4922 vty_out (vty, " receive");
4923 vty_out (vty, "%s", VTY_NEWLINE);
4924 }
4925
4926 /* Route reflector client. */
4927 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4928 && ! peer->af_group[afi][safi])
4929 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4930 VTY_NEWLINE);
4931
4932 /* Nexthop self. */
4933 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4934 && ! peer->af_group[afi][safi])
4935 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4936
4937 /* Remove private AS. */
4938 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4939 && ! peer->af_group[afi][safi])
4940 vty_out (vty, " neighbor %s remove-private-AS%s",
4941 addr, VTY_NEWLINE);
4942
4943 /* send-community print. */
4944 if (! peer->af_group[afi][safi])
4945 {
4946 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4947 {
4948 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4949 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4950 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4951 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4952 vty_out (vty, " neighbor %s send-community extended%s",
4953 addr, VTY_NEWLINE);
4954 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4955 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4956 }
4957 else
4958 {
4959 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4960 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4961 vty_out (vty, " no neighbor %s send-community both%s",
4962 addr, VTY_NEWLINE);
4963 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4964 vty_out (vty, " no neighbor %s send-community extended%s",
4965 addr, VTY_NEWLINE);
4966 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4967 vty_out (vty, " no neighbor %s send-community%s",
4968 addr, VTY_NEWLINE);
4969 }
4970 }
4971
4972 /* Default information */
4973 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4974 && ! peer->af_group[afi][safi])
4975 {
4976 vty_out (vty, " neighbor %s default-originate", addr);
4977 if (peer->default_rmap[afi][safi].name)
4978 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4979 vty_out (vty, "%s", VTY_NEWLINE);
4980 }
4981
4982 /* Soft reconfiguration inbound. */
4983 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4984 if (! peer->af_group[afi][safi] ||
4985 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4986 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4987 VTY_NEWLINE);
4988
4989 /* maximum-prefix. */
4990 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4991 if (! peer->af_group[afi][safi]
4992 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004993 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004994 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4995 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004996 {
hasso0a486e52005-02-01 20:57:17 +00004997 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4998 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4999 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5000 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5001 vty_out (vty, " warning-only");
5002 if (peer->pmax_restart[afi][safi])
5003 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5004 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005005 }
paul718e3742002-12-13 20:15:29 +00005006
5007 /* Route server client. */
5008 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5009 && ! peer->af_group[afi][safi])
5010 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5011
Dylan Hall3cf12882011-10-27 15:28:17 +04005012 /* Nexthop-local unchanged. */
5013 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5014 && ! peer->af_group[afi][safi])
5015 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5016
paul718e3742002-12-13 20:15:29 +00005017 /* Allow AS in. */
5018 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5019 if (! peer_group_active (peer)
5020 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5021 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5022 {
5023 if (peer->allowas_in[afi][safi] == 3)
5024 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5025 else
5026 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5027 peer->allowas_in[afi][safi], VTY_NEWLINE);
5028 }
5029
5030 /* Filter. */
5031 bgp_config_write_filter (vty, peer, afi, safi);
5032
5033 /* atribute-unchanged. */
5034 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5035 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5036 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5037 && ! peer->af_group[afi][safi])
5038 {
5039 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5040 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5041 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5042 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5043 else
5044 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5045 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5046 " as-path" : "",
5047 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5048 " next-hop" : "",
5049 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5050 " med" : "", VTY_NEWLINE);
5051 }
5052}
5053
5054/* Display "address-family" configuration header. */
5055void
5056bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5057 int *write)
5058{
5059 if (*write)
5060 return;
5061
5062 if (afi == AFI_IP && safi == SAFI_UNICAST)
5063 return;
5064
5065 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5066
5067 if (afi == AFI_IP)
5068 {
5069 if (safi == SAFI_MULTICAST)
5070 vty_out (vty, "ipv4 multicast");
5071 else if (safi == SAFI_MPLS_VPN)
5072 vty_out (vty, "vpnv4 unicast");
5073 }
5074 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005075 {
5076 vty_out (vty, "ipv6");
5077
5078 if (safi == SAFI_MULTICAST)
5079 vty_out (vty, " multicast");
5080 }
paul718e3742002-12-13 20:15:29 +00005081
5082 vty_out (vty, "%s", VTY_NEWLINE);
5083
5084 *write = 1;
5085}
5086
5087/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005088static int
paul718e3742002-12-13 20:15:29 +00005089bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5090 safi_t safi)
5091{
5092 int write = 0;
5093 struct peer *peer;
5094 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005095 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005096
5097 bgp_config_write_network (vty, bgp, afi, safi, &write);
5098
5099 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5100
paul1eb8ef22005-04-07 07:30:20 +00005101 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005102 {
5103 if (group->conf->afc[afi][safi])
5104 {
5105 bgp_config_write_family_header (vty, afi, safi, &write);
5106 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5107 }
5108 }
paul1eb8ef22005-04-07 07:30:20 +00005109 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005110 {
5111 if (peer->afc[afi][safi])
5112 {
5113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5114 {
5115 bgp_config_write_family_header (vty, afi, safi, &write);
5116 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5117 }
5118 }
5119 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005120
5121 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5122
paul718e3742002-12-13 20:15:29 +00005123 if (write)
5124 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5125
5126 return write;
5127}
5128
5129int
5130bgp_config_write (struct vty *vty)
5131{
5132 int write = 0;
5133 struct bgp *bgp;
5134 struct peer_group *group;
5135 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005136 struct listnode *node, *nnode;
5137 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005138
5139 /* BGP Multiple instance. */
5140 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5141 {
5142 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5143 write++;
5144 }
5145
5146 /* BGP Config type. */
5147 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5148 {
5149 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5150 write++;
5151 }
5152
5153 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005154 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005155 {
5156 if (write)
5157 vty_out (vty, "!%s", VTY_NEWLINE);
5158
5159 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005160 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005161
5162 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5163 {
5164 if (bgp->name)
5165 vty_out (vty, " view %s", bgp->name);
5166 }
5167 vty_out (vty, "%s", VTY_NEWLINE);
5168
5169 /* No Synchronization */
5170 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5171 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5172
5173 /* BGP fast-external-failover. */
5174 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5175 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5176
5177 /* BGP router ID. */
5178 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5179 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5180 VTY_NEWLINE);
5181
paul848973c2003-08-13 00:32:49 +00005182 /* BGP log-neighbor-changes. */
5183 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5184 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5185
paul718e3742002-12-13 20:15:29 +00005186 /* BGP configuration. */
5187 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5188 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5189
5190 /* BGP default ipv4-unicast. */
5191 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5192 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5193
5194 /* BGP default local-preference. */
5195 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5196 vty_out (vty, " bgp default local-preference %d%s",
5197 bgp->default_local_pref, VTY_NEWLINE);
5198
5199 /* BGP client-to-client reflection. */
5200 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5201 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5202
5203 /* BGP cluster ID. */
5204 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5205 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5206 VTY_NEWLINE);
5207
hassoe0701b72004-05-20 09:19:34 +00005208 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005209 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005210 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5211 VTY_NEWLINE);
5212
5213 /* Confederation peer */
5214 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005215 {
hassoe0701b72004-05-20 09:19:34 +00005216 int i;
paul718e3742002-12-13 20:15:29 +00005217
hassoe0701b72004-05-20 09:19:34 +00005218 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005219
hassoe0701b72004-05-20 09:19:34 +00005220 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005221 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005222
hassoe0701b72004-05-20 09:19:34 +00005223 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005224 }
5225
5226 /* BGP enforce-first-as. */
5227 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5228 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5229
5230 /* BGP deterministic-med. */
5231 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5232 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005233
5234 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005235 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5236 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5237 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005238 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5239 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5240
paul718e3742002-12-13 20:15:29 +00005241 /* BGP bestpath method. */
5242 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5243 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005244 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5245 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005246 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5247 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5248 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5249 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5250 {
5251 vty_out (vty, " bgp bestpath med");
5252 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5253 vty_out (vty, " confed");
5254 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5255 vty_out (vty, " missing-as-worst");
5256 vty_out (vty, "%s", VTY_NEWLINE);
5257 }
5258
5259 /* BGP network import check. */
5260 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5261 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5262
5263 /* BGP scan interval. */
5264 bgp_config_write_scan_time (vty);
5265
5266 /* BGP flag dampening. */
5267 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5268 BGP_CONFIG_DAMPENING))
5269 bgp_config_write_damp (vty);
5270
5271 /* BGP static route configuration. */
5272 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5273
5274 /* BGP redistribute configuration. */
5275 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5276
5277 /* BGP timers configuration. */
5278 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5279 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5280 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5281 bgp->default_holdtime, VTY_NEWLINE);
5282
5283 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005284 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005285 {
5286 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5287 }
5288
5289 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005290 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005291 {
5292 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5293 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5294 }
5295
Josh Bailey165b5ff2011-07-20 20:43:22 -07005296 /* maximum-paths */
5297 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5298
paul718e3742002-12-13 20:15:29 +00005299 /* Distance configuration. */
5300 bgp_config_write_distance (vty, bgp);
5301
5302 /* No auto-summary */
5303 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5304 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5305
5306 /* IPv4 multicast configuration. */
5307 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5308
5309 /* IPv4 VPN configuration. */
5310 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5311
5312 /* IPv6 unicast configuration. */
5313 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5314
Paul Jakma37a217a2007-04-10 19:20:29 +00005315 /* IPv6 multicast configuration. */
5316 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5317
paul718e3742002-12-13 20:15:29 +00005318 write++;
5319 }
5320 return write;
5321}
5322
5323void
paul94f2b392005-06-28 12:44:16 +00005324bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005325{
5326 memset (&bgp_master, 0, sizeof (struct bgp_master));
5327
5328 bm = &bgp_master;
5329 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005330 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005331 bm->port = BGP_PORT_DEFAULT;
5332 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005333 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005334}
paul200df112005-06-01 11:17:05 +00005335
paul718e3742002-12-13 20:15:29 +00005336
Paul Jakma7621f332012-05-01 16:24:35 +01005337int
5338bgp_socket_init (void)
5339{
5340 /* Create BGP server socket */
5341 if (bgp_socket (bm->port, bm->address) < 0)
5342 return BGP_ERR_INVALID_VALUE;
5343 return 0;
5344}
5345
paul718e3742002-12-13 20:15:29 +00005346void
paul94f2b392005-06-28 12:44:16 +00005347bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005348{
paul718e3742002-12-13 20:15:29 +00005349 /* BGP VTY commands installation. */
5350 bgp_vty_init ();
5351
paul718e3742002-12-13 20:15:29 +00005352 /* Init zebra. */
5353 bgp_zebra_init ();
5354
5355 /* BGP inits. */
5356 bgp_attr_init ();
5357 bgp_debug_init ();
5358 bgp_dump_init ();
5359 bgp_route_init ();
5360 bgp_route_map_init ();
5361 bgp_scan_init ();
5362 bgp_mplsvpn_init ();
5363
5364 /* Access list initialize. */
5365 access_list_init ();
5366 access_list_add_hook (peer_distribute_update);
5367 access_list_delete_hook (peer_distribute_update);
5368
5369 /* Filter list initialize. */
5370 bgp_filter_init ();
5371 as_list_add_hook (peer_aslist_update);
5372 as_list_delete_hook (peer_aslist_update);
5373
5374 /* Prefix list initialize.*/
5375 prefix_list_init ();
5376 prefix_list_add_hook (peer_prefix_list_update);
5377 prefix_list_delete_hook (peer_prefix_list_update);
5378
5379 /* Community list initialize. */
5380 bgp_clist = community_list_init ();
5381
5382#ifdef HAVE_SNMP
5383 bgp_snmp_init ();
5384#endif /* HAVE_SNMP */
5385}
paul545acaf2004-04-20 15:13:15 +00005386
5387void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005388bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005389{
paul545acaf2004-04-20 15:13:15 +00005390 struct bgp *bgp;
5391 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005392 struct listnode *node, *nnode;
5393 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005394
paul1eb8ef22005-04-07 07:30:20 +00005395 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5396 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005397 if (peer->status == Established)
5398 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5399 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005400
paul545acaf2004-04-20 15:13:15 +00005401 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005402
paule210cf92005-06-15 19:15:35 +00005403 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005404 {
5405 work_queue_free (bm->process_main_queue);
5406 bm->process_main_queue = NULL;
5407 }
paule210cf92005-06-15 19:15:35 +00005408 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005409 {
5410 work_queue_free (bm->process_rsclient_queue);
5411 bm->process_rsclient_queue = NULL;
5412 }
paul545acaf2004-04-20 15:13:15 +00005413}