blob: bda35ae592b4df1a7b15f33bf01983073d2bcc6a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
hasso18a6dce2004-10-03 18:18:34 +000067extern struct in_addr router_id_zebra;
68
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
Paul Jakmad664ae12007-08-31 14:27:37 +010084 case BGP_OPT_ALWAYS_OPEN:
paul718e3742002-12-13 20:15:29 +000085 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:
Paul Jakmad664ae12007-08-31 14:27:37 +0100104 case BGP_OPT_ALWAYS_OPEN:
paul718e3742002-12-13 20:15:29 +0000105 UNSET_FLAG (bm->options, flag);
106 break;
107 default:
108 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000109 }
110 return 0;
111}
112
113int
114bgp_option_check (int flag)
115{
116 return CHECK_FLAG (bm->options, flag);
117}
118
119/* BGP flag manipulation. */
120int
121bgp_flag_set (struct bgp *bgp, int flag)
122{
123 SET_FLAG (bgp->flags, flag);
124 return 0;
125}
126
127int
128bgp_flag_unset (struct bgp *bgp, int flag)
129{
130 UNSET_FLAG (bgp->flags, flag);
131 return 0;
132}
133
134int
135bgp_flag_check (struct bgp *bgp, int flag)
136{
137 return CHECK_FLAG (bgp->flags, flag);
138}
139
140/* Internal function to set BGP structure configureation flag. */
141static void
142bgp_config_set (struct bgp *bgp, int config)
143{
144 SET_FLAG (bgp->config, config);
145}
146
147static void
148bgp_config_unset (struct bgp *bgp, int config)
149{
150 UNSET_FLAG (bgp->config, config);
151}
152
153static int
154bgp_config_check (struct bgp *bgp, int config)
155{
156 return CHECK_FLAG (bgp->config, config);
157}
158
159/* Set BGP router identifier. */
160int
161bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
162{
163 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000165
166 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
167 && IPV4_ADDR_SAME (&bgp->router_id, id))
168 return 0;
169
170 IPV4_ADDR_COPY (&bgp->router_id, id);
171 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
172
173 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000175 {
176 IPV4_ADDR_COPY (&peer->local_id, id);
177
178 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000179 {
180 peer->last_reset = PEER_DOWN_RID_CHANGE;
181 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
182 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
183 }
paul718e3742002-12-13 20:15:29 +0000184 }
185 return 0;
186}
187
paul718e3742002-12-13 20:15:29 +0000188/* BGP's cluster-id control. */
189int
190bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
191{
192 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000193 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000194
195 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
196 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
197 return 0;
198
199 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
200 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
201
202 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000204 {
205 if (peer_sort (peer) != BGP_PEER_IBGP)
206 continue;
207
208 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000209 {
210 peer->last_reset = PEER_DOWN_CLID_CHANGE;
211 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
212 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
213 }
paul718e3742002-12-13 20:15:29 +0000214 }
215 return 0;
216}
217
218int
219bgp_cluster_id_unset (struct bgp *bgp)
220{
221 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000223
224 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
225 return 0;
226
227 bgp->cluster_id.s_addr = 0;
228 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
229
230 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000231 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000232 {
233 if (peer_sort (peer) != BGP_PEER_IBGP)
234 continue;
235
236 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000237 {
238 peer->last_reset = PEER_DOWN_CLID_CHANGE;
239 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
240 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
241 }
paul718e3742002-12-13 20:15:29 +0000242 }
243 return 0;
244}
245
246/* BGP timer configuration. */
247int
248bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
249{
250 bgp->default_keepalive = (keepalive < holdtime / 3
251 ? keepalive : holdtime / 3);
252 bgp->default_holdtime = holdtime;
253
254 return 0;
255}
256
257int
258bgp_timers_unset (struct bgp *bgp)
259{
260 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
261 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
262
263 return 0;
264}
265
266/* BGP confederation configuration. */
267int
268bgp_confederation_id_set (struct bgp *bgp, as_t as)
269{
270 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000271 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000272 int already_confed;
273
274 if (as == 0)
275 return BGP_ERR_INVALID_AS;
276
277 /* Remember - were we doing confederation before? */
278 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
279 bgp->confed_id = as;
280 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
281
282 /* If we were doing confederation already, this is just an external
283 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
284 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000285 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000286 {
287 /* We're looking for peers who's AS is not local or part of our
288 confederation. */
289 if (already_confed)
290 {
291 if (peer_sort (peer) == BGP_PEER_EBGP)
292 {
293 peer->local_as = as;
294 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000295 {
296 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
297 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
298 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
299 }
300
paul718e3742002-12-13 20:15:29 +0000301 else
302 BGP_EVENT_ADD (peer, BGP_Stop);
303 }
304 }
305 else
306 {
307 /* Not doign confederation before, so reset every non-local
308 session */
309 if (peer_sort (peer) != BGP_PEER_IBGP)
310 {
311 /* Reset the local_as to be our EBGP one */
312 if (peer_sort (peer) == BGP_PEER_EBGP)
313 peer->local_as = as;
314 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000315 {
316 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
317 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
318 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
319 }
paul718e3742002-12-13 20:15:29 +0000320 else
321 BGP_EVENT_ADD (peer, BGP_Stop);
322 }
323 }
324 }
325 return 0;
326}
327
328int
329bgp_confederation_id_unset (struct bgp *bgp)
330{
331 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000332 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000333
334 bgp->confed_id = 0;
335 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
336
paul1eb8ef22005-04-07 07:30:20 +0000337 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000338 {
339 /* We're looking for peers who's AS is not local */
340 if (peer_sort (peer) != BGP_PEER_IBGP)
341 {
342 peer->local_as = bgp->as;
343 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000344 {
345 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
346 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
347 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
348 }
349
paul718e3742002-12-13 20:15:29 +0000350 else
351 BGP_EVENT_ADD (peer, BGP_Stop);
352 }
353 }
354 return 0;
355}
356
357/* Is an AS part of the confed or not? */
358int
359bgp_confederation_peers_check (struct bgp *bgp, as_t as)
360{
361 int i;
362
363 if (! bgp)
364 return 0;
365
366 for (i = 0; i < bgp->confed_peers_cnt; i++)
367 if (bgp->confed_peers[i] == as)
368 return 1;
369
370 return 0;
371}
372
373/* Add an AS to the confederation set. */
374int
375bgp_confederation_peers_add (struct bgp *bgp, as_t as)
376{
377 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000378 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000379
380 if (! bgp)
381 return BGP_ERR_INVALID_BGP;
382
383 if (bgp->as == as)
384 return BGP_ERR_INVALID_AS;
385
386 if (bgp_confederation_peers_check (bgp, as))
387 return -1;
388
389 if (bgp->confed_peers)
390 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
391 bgp->confed_peers,
392 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
393 else
394 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
395 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
396
397 bgp->confed_peers[bgp->confed_peers_cnt] = as;
398 bgp->confed_peers_cnt++;
399
400 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
401 {
paul1eb8ef22005-04-07 07:30:20 +0000402 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000403 {
404 if (peer->as == as)
405 {
406 peer->local_as = bgp->as;
407 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000408 {
409 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
410 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
411 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
412 }
paul718e3742002-12-13 20:15:29 +0000413 else
414 BGP_EVENT_ADD (peer, BGP_Stop);
415 }
416 }
417 }
418 return 0;
419}
420
421/* Delete an AS from the confederation set. */
422int
423bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
424{
425 int i;
426 int j;
427 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000428 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000429
430 if (! bgp)
431 return -1;
432
433 if (! bgp_confederation_peers_check (bgp, as))
434 return -1;
435
436 for (i = 0; i < bgp->confed_peers_cnt; i++)
437 if (bgp->confed_peers[i] == as)
438 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
439 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
440
441 bgp->confed_peers_cnt--;
442
443 if (bgp->confed_peers_cnt == 0)
444 {
445 if (bgp->confed_peers)
446 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
447 bgp->confed_peers = NULL;
448 }
449 else
450 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
451 bgp->confed_peers,
452 bgp->confed_peers_cnt * sizeof (as_t));
453
454 /* Now reset any peer who's remote AS has just been removed from the
455 CONFED */
456 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
457 {
paul1eb8ef22005-04-07 07:30:20 +0000458 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000459 {
460 if (peer->as == as)
461 {
462 peer->local_as = bgp->confed_id;
463 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000464 {
465 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
466 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
467 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
468 }
paul718e3742002-12-13 20:15:29 +0000469 else
470 BGP_EVENT_ADD (peer, BGP_Stop);
471 }
472 }
473 }
474
475 return 0;
476}
477
478/* Local preference configuration. */
479int
480bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
481{
482 if (! bgp)
483 return -1;
484
paul718e3742002-12-13 20:15:29 +0000485 bgp->default_local_pref = local_pref;
486
487 return 0;
488}
489
490int
491bgp_default_local_preference_unset (struct bgp *bgp)
492{
493 if (! bgp)
494 return -1;
495
paul718e3742002-12-13 20:15:29 +0000496 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
497
498 return 0;
499}
500
paulfee0f4c2004-09-13 05:12:46 +0000501/* If peer is RSERVER_CLIENT in at least one address family and is not member
502 of a peer_group for that family, return 1.
503 Used to check wether the peer is included in list bgp->rsclient. */
504int
505peer_rsclient_active (struct peer *peer)
506{
507 int i;
508 int j;
509
510 for (i=AFI_IP; i < AFI_MAX; i++)
511 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
512 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
513 && ! peer->af_group[i][j])
514 return 1;
515 return 0;
516}
517
pauleb821182004-05-01 08:44:08 +0000518/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000519static int
520peer_cmp (struct peer *p1, struct peer *p2)
521{
pauleb821182004-05-01 08:44:08 +0000522 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000523}
524
525int
526peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
527{
528 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
529}
530
531/* Reset all address family specific configuration. */
532static void
533peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
534{
535 int i;
536 struct bgp_filter *filter;
537 char orf_name[BUFSIZ];
538
539 filter = &peer->filter[afi][safi];
540
541 /* Clear neighbor filter and route-map */
542 for (i = FILTER_IN; i < FILTER_MAX; i++)
543 {
544 if (filter->dlist[i].name)
545 {
546 free (filter->dlist[i].name);
547 filter->dlist[i].name = NULL;
548 }
549 if (filter->plist[i].name)
550 {
551 free (filter->plist[i].name);
552 filter->plist[i].name = NULL;
553 }
554 if (filter->aslist[i].name)
555 {
556 free (filter->aslist[i].name);
557 filter->aslist[i].name = NULL;
558 }
paulfee0f4c2004-09-13 05:12:46 +0000559 }
560 for (i = RMAP_IN; i < RMAP_MAX; i++)
561 {
paul718e3742002-12-13 20:15:29 +0000562 if (filter->map[i].name)
563 {
564 free (filter->map[i].name);
565 filter->map[i].name = NULL;
566 }
567 }
568
569 /* Clear unsuppress map. */
570 if (filter->usmap.name)
571 free (filter->usmap.name);
572 filter->usmap.name = NULL;
573 filter->usmap.map = NULL;
574
575 /* Clear neighbor's all address family flags. */
576 peer->af_flags[afi][safi] = 0;
577
578 /* Clear neighbor's all address family sflags. */
579 peer->af_sflags[afi][safi] = 0;
580
581 /* Clear neighbor's all address family capabilities. */
582 peer->af_cap[afi][safi] = 0;
583
584 /* Clear ORF info */
585 peer->orf_plist[afi][safi] = NULL;
586 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
587 prefix_bgp_orf_remove_all (orf_name);
588
589 /* Set default neighbor send-community. */
590 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
591 {
592 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
593 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
594 }
595
596 /* Clear neighbor default_originate_rmap */
597 if (peer->default_rmap[afi][safi].name)
598 free (peer->default_rmap[afi][safi].name);
599 peer->default_rmap[afi][safi].name = NULL;
600 peer->default_rmap[afi][safi].map = NULL;
601
602 /* Clear neighbor maximum-prefix */
603 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000604 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000605}
606
607/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000608static void
paul718e3742002-12-13 20:15:29 +0000609peer_global_config_reset (struct peer *peer)
610{
611 peer->weight = 0;
612 peer->change_local_as = 0;
613 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
614 if (peer->update_source)
615 {
616 sockunion_free (peer->update_source);
617 peer->update_source = NULL;
618 }
619 if (peer->update_if)
620 {
621 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
622 peer->update_if = NULL;
623 }
624
625 if (peer_sort (peer) == BGP_PEER_IBGP)
626 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
627 else
628 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
629
630 peer->flags = 0;
631 peer->config = 0;
632 peer->holdtime = 0;
633 peer->keepalive = 0;
634 peer->connect = 0;
635 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
636}
637
638/* Check peer's AS number and determin is this peer IBGP or EBGP */
639int
640peer_sort (struct peer *peer)
641{
642 struct bgp *bgp;
643
644 bgp = peer->bgp;
645
646 /* Peer-group */
647 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
648 {
649 if (peer->as)
650 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
651 else
652 {
653 struct peer *peer1;
654 peer1 = listnode_head (peer->group->peer);
655 if (peer1)
656 return (peer1->local_as == peer1->as
657 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
658 }
659 return BGP_PEER_INTERNAL;
660 }
661
662 /* Normal peer */
663 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
664 {
665 if (peer->local_as == 0)
666 return BGP_PEER_INTERNAL;
667
668 if (peer->local_as == peer->as)
669 {
670 if (peer->local_as == bgp->confed_id)
671 return BGP_PEER_EBGP;
672 else
673 return BGP_PEER_IBGP;
674 }
675
676 if (bgp_confederation_peers_check (bgp, peer->as))
677 return BGP_PEER_CONFED;
678
679 return BGP_PEER_EBGP;
680 }
681 else
682 {
683 return (peer->local_as == 0
684 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
685 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
686 }
687}
688
paul200df112005-06-01 11:17:05 +0000689static inline void
690peer_free (struct peer *peer)
691{
Paul Jakmaca058a32006-09-14 02:58:49 +0000692 assert (peer->status == Deleted);
693
694 /* this /ought/ to have been done already through bgp_stop earlier,
695 * but just to be sure..
696 */
697 bgp_timer_set (peer);
698 BGP_READ_OFF (peer->t_read);
699 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000700 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000701
paul200df112005-06-01 11:17:05 +0000702 if (peer->desc)
703 XFREE (MTYPE_PEER_DESC, peer->desc);
704
705 /* Free allocated host character. */
706 if (peer->host)
707 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
708
709 /* Update source configuration. */
710 if (peer->update_source)
711 sockunion_free (peer->update_source);
712
713 if (peer->update_if)
714 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000715
716 if (peer->clear_node_queue)
717 work_queue_free (peer->clear_node_queue);
718
Paul Jakmaca058a32006-09-14 02:58:49 +0000719 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000720 memset (peer, 0, sizeof (struct peer));
721
722 XFREE (MTYPE_BGP_PEER, peer);
723}
724
725/* increase reference count on a struct peer */
726struct peer *
727peer_lock (struct peer *peer)
728{
729 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000730 assert (peer->status != Deleted);
731
paul200df112005-06-01 11:17:05 +0000732 peer->lock++;
733
734 return peer;
735}
736
737/* decrease reference count on a struct peer
738 * struct peer is freed and NULL returned if last reference
739 */
740struct peer *
741peer_unlock (struct peer *peer)
742{
743 assert (peer && (peer->lock > 0));
744
745 peer->lock--;
746
747 if (peer->lock == 0)
748 {
749#if 0
750 zlog_debug ("unlocked and freeing");
751 zlog_backtrace (LOG_DEBUG);
752#endif
753 peer_free (peer);
754 return NULL;
755 }
756
757#if 0
758 if (peer->lock == 1)
759 {
760 zlog_debug ("unlocked to 1");
761 zlog_backtrace (LOG_DEBUG);
762 }
763#endif
764
765 return peer;
766}
767
768/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000769static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000770peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000771{
772 afi_t afi;
773 safi_t safi;
774 struct peer *peer;
775 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000776
777 /* bgp argument is absolutely required */
778 assert (bgp);
779 if (!bgp)
780 return NULL;
781
paul718e3742002-12-13 20:15:29 +0000782 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000783 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000784
785 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000786 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000787 peer->v_start = BGP_INIT_START_TIMER;
788 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
789 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
790 peer->status = Idle;
791 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000792 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000793 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000794 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000795 peer = peer_lock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000796
797 /* Set default flags. */
798 for (afi = AFI_IP; afi < AFI_MAX; afi++)
799 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
800 {
801 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
802 {
803 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
804 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
805 }
806 peer->orf_plist[afi][safi] = NULL;
807 }
808 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
809
810 /* Create buffers. */
811 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
812 peer->obuf = stream_fifo_new ();
813 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
814
815 bgp_sync_init (peer);
816
817 /* Get service port number. */
818 sp = getservbyname ("bgp", "tcp");
819 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
820
821 return peer;
822}
823
824/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000825static struct peer *
paul718e3742002-12-13 20:15:29 +0000826peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
827 as_t remote_as, afi_t afi, safi_t safi)
828{
829 int active;
830 struct peer *peer;
831 char buf[SU_ADDRSTRLEN];
832
Paul Jakma6f585442006-10-22 19:13:07 +0000833 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000834 peer->su = *su;
835 peer->local_as = local_as;
836 peer->as = remote_as;
837 peer->local_id = bgp->router_id;
838 peer->v_holdtime = bgp->default_holdtime;
839 peer->v_keepalive = bgp->default_keepalive;
840 if (peer_sort (peer) == BGP_PEER_IBGP)
841 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
842 else
843 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000844
845 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000846 listnode_add_sort (bgp->peer, peer);
847
848 active = peer_active (peer);
849
850 if (afi && safi)
851 peer->afc[afi][safi] = 1;
852
853 /* Last read time set */
854 peer->readtime = time (NULL);
855
paul848973c2003-08-13 00:32:49 +0000856 /* Last reset time set */
857 peer->resettime = time (NULL);
858
paul718e3742002-12-13 20:15:29 +0000859 /* Default TTL set. */
860 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
861
862 /* Make peer's address string. */
863 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000864 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000865
866 /* Set up peer's events and timers. */
867 if (! active && peer_active (peer))
868 bgp_timer_set (peer);
869
870 return peer;
871}
872
pauleb821182004-05-01 08:44:08 +0000873/* Make accept BGP peer. Called from bgp_accept (). */
874struct peer *
875peer_create_accept (struct bgp *bgp)
876{
877 struct peer *peer;
878
Paul Jakma6f585442006-10-22 19:13:07 +0000879 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000880
881 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000882 listnode_add_sort (bgp->peer, peer);
883
884 return peer;
885}
886
paul718e3742002-12-13 20:15:29 +0000887/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000888static void
paul718e3742002-12-13 20:15:29 +0000889peer_as_change (struct peer *peer, as_t as)
890{
891 int type;
892
893 /* Stop peer. */
894 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
895 {
896 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000897 {
898 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
901 }
paul718e3742002-12-13 20:15:29 +0000902 else
903 BGP_EVENT_ADD (peer, BGP_Stop);
904 }
905 type = peer_sort (peer);
906 peer->as = as;
907
paul848973c2003-08-13 00:32:49 +0000908 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
909 && ! bgp_confederation_peers_check (peer->bgp, as)
910 && peer->bgp->as != as)
911 peer->local_as = peer->bgp->confed_id;
912 else
913 peer->local_as = peer->bgp->as;
914
paul718e3742002-12-13 20:15:29 +0000915 /* Advertisement-interval reset */
916 if (peer_sort (peer) == BGP_PEER_IBGP)
917 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
918 else
919 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
920
921 /* TTL reset */
922 if (peer_sort (peer) == BGP_PEER_IBGP)
923 peer->ttl = 255;
924 else if (type == BGP_PEER_IBGP)
925 peer->ttl = 1;
926
927 /* reflector-client reset */
928 if (peer_sort (peer) != BGP_PEER_IBGP)
929 {
930 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
931 PEER_FLAG_REFLECTOR_CLIENT);
932 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
933 PEER_FLAG_REFLECTOR_CLIENT);
934 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
935 PEER_FLAG_REFLECTOR_CLIENT);
936 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
937 PEER_FLAG_REFLECTOR_CLIENT);
938 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
939 PEER_FLAG_REFLECTOR_CLIENT);
940 }
941
942 /* local-as reset */
943 if (peer_sort (peer) != BGP_PEER_EBGP)
944 {
945 peer->change_local_as = 0;
946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
947 }
948}
949
950/* If peer does not exist, create new one. If peer already exists,
951 set AS number to the peer. */
952int
953peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
954 afi_t afi, safi_t safi)
955{
956 struct peer *peer;
957 as_t local_as;
958
959 peer = peer_lookup (bgp, su);
960
961 if (peer)
962 {
963 /* When this peer is a member of peer-group. */
964 if (peer->group)
965 {
966 if (peer->group->conf->as)
967 {
968 /* Return peer group's AS number. */
969 *as = peer->group->conf->as;
970 return BGP_ERR_PEER_GROUP_MEMBER;
971 }
972 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
973 {
974 if (bgp->as != *as)
975 {
976 *as = peer->as;
977 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
978 }
979 }
980 else
981 {
982 if (bgp->as == *as)
983 {
984 *as = peer->as;
985 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
986 }
987 }
988 }
989
990 /* Existing peer's AS number change. */
991 if (peer->as != *as)
992 peer_as_change (peer, *as);
993 }
994 else
995 {
996
997 /* If the peer is not part of our confederation, and its not an
998 iBGP peer then spoof the source AS */
999 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1000 && ! bgp_confederation_peers_check (bgp, *as)
1001 && bgp->as != *as)
1002 local_as = bgp->confed_id;
1003 else
1004 local_as = bgp->as;
1005
1006 /* If this is IPv4 unicast configuration and "no bgp default
1007 ipv4-unicast" is specified. */
1008
1009 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1010 && afi == AFI_IP && safi == SAFI_UNICAST)
1011 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1012 else
1013 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1014 }
1015
1016 return 0;
1017}
1018
1019/* Activate the peer or peer group for specified AFI and SAFI. */
1020int
1021peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1022{
1023 int active;
1024
1025 if (peer->afc[afi][safi])
1026 return 0;
1027
1028 /* Activate the address family configuration. */
1029 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1030 peer->afc[afi][safi] = 1;
1031 else
1032 {
1033 active = peer_active (peer);
1034
1035 peer->afc[afi][safi] = 1;
1036
1037 if (! active && peer_active (peer))
1038 bgp_timer_set (peer);
1039 else
1040 {
1041 if (peer->status == Established)
1042 {
1043 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1044 {
1045 peer->afc_adv[afi][safi] = 1;
1046 bgp_capability_send (peer, afi, safi,
1047 CAPABILITY_CODE_MP,
1048 CAPABILITY_ACTION_SET);
1049 if (peer->afc_recv[afi][safi])
1050 {
1051 peer->afc_nego[afi][safi] = 1;
1052 bgp_announce_route (peer, afi, safi);
1053 }
1054 }
1055 else
hassoe0701b72004-05-20 09:19:34 +00001056 {
1057 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1058 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1059 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1060 }
paul718e3742002-12-13 20:15:29 +00001061 }
1062 }
1063 }
1064 return 0;
1065}
1066
1067int
1068peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1069{
1070 struct peer_group *group;
1071 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001072 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001073
1074 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1075 {
1076 group = peer->group;
1077
paul1eb8ef22005-04-07 07:30:20 +00001078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001079 {
1080 if (peer1->af_group[afi][safi])
1081 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1082 }
1083 }
1084 else
1085 {
1086 if (peer->af_group[afi][safi])
1087 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1088 }
1089
1090 if (! peer->afc[afi][safi])
1091 return 0;
1092
1093 /* De-activate the address family configuration. */
1094 peer->afc[afi][safi] = 0;
1095 peer_af_flag_reset (peer, afi, safi);
1096
1097 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1098 {
1099 if (peer->status == Established)
1100 {
1101 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1102 {
1103 peer->afc_adv[afi][safi] = 0;
1104 peer->afc_nego[afi][safi] = 0;
1105
1106 if (peer_active_nego (peer))
1107 {
1108 bgp_capability_send (peer, afi, safi,
1109 CAPABILITY_CODE_MP,
1110 CAPABILITY_ACTION_UNSET);
1111 bgp_clear_route (peer, afi, safi);
1112 peer->pcount[afi][safi] = 0;
1113 }
1114 else
hassoe0701b72004-05-20 09:19:34 +00001115 {
1116 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1117 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1118 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1119 }
paul718e3742002-12-13 20:15:29 +00001120 }
1121 else
hassoe0701b72004-05-20 09:19:34 +00001122 {
1123 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1124 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1125 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1126 }
paul718e3742002-12-13 20:15:29 +00001127 }
1128 }
1129 return 0;
1130}
1131
hasso93406d82005-02-02 14:40:33 +00001132void
1133peer_nsf_stop (struct peer *peer)
1134{
1135 afi_t afi;
1136 safi_t safi;
1137
1138 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1139 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1140
1141 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1142 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1143 peer->nsf[afi][safi] = 0;
1144
1145 if (peer->t_gr_restart)
1146 {
1147 BGP_TIMER_OFF (peer->t_gr_restart);
1148 if (BGP_DEBUG (events, EVENTS))
1149 zlog_debug ("%s graceful restart timer stopped", peer->host);
1150 }
1151 if (peer->t_gr_stale)
1152 {
1153 BGP_TIMER_OFF (peer->t_gr_stale);
1154 if (BGP_DEBUG (events, EVENTS))
1155 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1156 }
1157 bgp_clear_route_all (peer);
1158}
1159
Paul Jakmaca058a32006-09-14 02:58:49 +00001160/* Delete peer from confguration.
1161 *
1162 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1163 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1164 *
1165 * This function /should/ take care to be idempotent, to guard against
1166 * it being called multiple times through stray events that come in
1167 * that happen to result in this function being called again. That
1168 * said, getting here for a "Deleted" peer is a bug in the neighbour
1169 * FSM.
1170 */
paul718e3742002-12-13 20:15:29 +00001171int
1172peer_delete (struct peer *peer)
1173{
1174 int i;
1175 afi_t afi;
1176 safi_t safi;
1177 struct bgp *bgp;
1178 struct bgp_filter *filter;
1179
Paul Jakmaca058a32006-09-14 02:58:49 +00001180 assert (peer->status != Deleted);
1181
paul718e3742002-12-13 20:15:29 +00001182 bgp = peer->bgp;
1183
hasso93406d82005-02-02 14:40:33 +00001184 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1185 peer_nsf_stop (peer);
1186
paul718e3742002-12-13 20:15:29 +00001187 /* If this peer belongs to peer group. Clearn up the
1188 relationship. */
1189 if (peer->group)
1190 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001191 struct listnode *pn;
1192
1193 if ((pn = listnode_lookup (peer->group->peer, peer)))
1194 {
1195 peer = peer_unlock (peer); /* group->peer list reference */
1196 list_delete_node (peer->group->peer, pn);
1197 }
paul718e3742002-12-13 20:15:29 +00001198 peer->group = NULL;
1199 }
paul200df112005-06-01 11:17:05 +00001200
paul718e3742002-12-13 20:15:29 +00001201 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001202 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1203 * executed after peer structure is deleted.
1204 */
hassoe0701b72004-05-20 09:19:34 +00001205 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001206 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001207 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001208
1209 /* Password configuration */
1210 if (peer->password)
1211 {
1212 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1213 peer->password = NULL;
1214
1215 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1216 bgp_md5_set (peer);
1217 }
1218
Paul Jakmaca058a32006-09-14 02:58:49 +00001219 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001220
paul718e3742002-12-13 20:15:29 +00001221 /* Delete from all peer list. */
1222 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001223 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001224 struct listnode *pn;
paul200df112005-06-01 11:17:05 +00001225
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 if ((pn = listnode_lookup (bgp->peer, peer)))
1227 {
1228 peer_unlock (peer); /* bgp peer list reference */
1229 list_delete_node (bgp->peer, pn);
1230 }
1231
1232 if (peer_rsclient_active (peer)
1233 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001234 {
1235 peer_unlock (peer); /* rsclient list reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001236 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001237 }
paulfee0f4c2004-09-13 05:12:46 +00001238 }
1239
1240 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1241 member of a peer_group. */
1242 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1243 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1244 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001245 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001246
paul200df112005-06-01 11:17:05 +00001247 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001248 if (peer->ibuf)
1249 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001250 if (peer->obuf)
1251 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001252 if (peer->work)
1253 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001254 peer->obuf = NULL;
1255 peer->work = peer->ibuf = NULL;
1256
paul718e3742002-12-13 20:15:29 +00001257 /* Local and remote addresses. */
1258 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001259 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001260 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001261 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001262 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001263
paul718e3742002-12-13 20:15:29 +00001264 /* Free filter related memory. */
1265 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1266 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1267 {
1268 filter = &peer->filter[afi][safi];
1269
1270 for (i = FILTER_IN; i < FILTER_MAX; i++)
1271 {
1272 if (filter->dlist[i].name)
1273 free (filter->dlist[i].name);
1274 if (filter->plist[i].name)
1275 free (filter->plist[i].name);
1276 if (filter->aslist[i].name)
1277 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001278
1279 filter->dlist[i].name = NULL;
1280 filter->plist[i].name = NULL;
1281 filter->aslist[i].name = NULL;
1282 }
1283 for (i = RMAP_IN; i < RMAP_MAX; i++)
1284 {
paul718e3742002-12-13 20:15:29 +00001285 if (filter->map[i].name)
1286 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001287 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001288 }
1289
1290 if (filter->usmap.name)
1291 free (filter->usmap.name);
1292
1293 if (peer->default_rmap[afi][safi].name)
1294 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001295
1296 filter->usmap.name = NULL;
1297 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001298 }
paul200df112005-06-01 11:17:05 +00001299
1300 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001301
1302 return 0;
1303}
1304
paul94f2b392005-06-28 12:44:16 +00001305static int
paul718e3742002-12-13 20:15:29 +00001306peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1307{
1308 return strcmp (g1->name, g2->name);
1309}
1310
1311/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001312static int
paul718e3742002-12-13 20:15:29 +00001313peer_group_active (struct peer *peer)
1314{
1315 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1316 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1317 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1318 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1319 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1320 return 1;
1321 return 0;
1322}
1323
1324/* Peer group cofiguration. */
1325static struct peer_group *
1326peer_group_new ()
1327{
1328 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1329 sizeof (struct peer_group));
1330}
1331
paul94f2b392005-06-28 12:44:16 +00001332static void
paul718e3742002-12-13 20:15:29 +00001333peer_group_free (struct peer_group *group)
1334{
1335 XFREE (MTYPE_PEER_GROUP, group);
1336}
1337
1338struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001339peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001340{
1341 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001342 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001343
paul1eb8ef22005-04-07 07:30:20 +00001344 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001345 {
1346 if (strcmp (group->name, name) == 0)
1347 return group;
1348 }
1349 return NULL;
1350}
1351
1352struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001353peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001354{
1355 struct peer_group *group;
1356
1357 group = peer_group_lookup (bgp, name);
1358 if (group)
1359 return group;
1360
1361 group = peer_group_new ();
1362 group->bgp = bgp;
1363 group->name = strdup (name);
1364 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001365 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001366 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1367 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1368 group->conf->host = strdup (name);
paul718e3742002-12-13 20:15:29 +00001369 group->conf->group = group;
1370 group->conf->as = 0;
1371 group->conf->ttl = 1;
1372 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1373 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1374 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1375 group->conf->keepalive = 0;
1376 group->conf->holdtime = 0;
1377 group->conf->connect = 0;
1378 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1379 listnode_add_sort (bgp->group, group);
1380
1381 return 0;
1382}
1383
paul94f2b392005-06-28 12:44:16 +00001384static void
paul718e3742002-12-13 20:15:29 +00001385peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1386 afi_t afi, safi_t safi)
1387{
1388 int in = FILTER_IN;
1389 int out = FILTER_OUT;
1390 struct peer *conf;
1391 struct bgp_filter *pfilter;
1392 struct bgp_filter *gfilter;
1393
1394 conf = group->conf;
1395 pfilter = &peer->filter[afi][safi];
1396 gfilter = &conf->filter[afi][safi];
1397
1398 /* remote-as */
1399 if (conf->as)
1400 peer->as = conf->as;
1401
1402 /* remote-as */
1403 if (conf->change_local_as)
1404 peer->change_local_as = conf->change_local_as;
1405
1406 /* TTL */
1407 peer->ttl = conf->ttl;
1408
1409 /* Weight */
1410 peer->weight = conf->weight;
1411
1412 /* peer flags apply */
1413 peer->flags = conf->flags;
1414 /* peer af_flags apply */
1415 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1416 /* peer config apply */
1417 peer->config = conf->config;
1418
1419 /* peer timers apply */
1420 peer->holdtime = conf->holdtime;
1421 peer->keepalive = conf->keepalive;
1422 peer->connect = conf->connect;
1423 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1424 peer->v_connect = conf->connect;
1425 else
1426 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1427
1428 /* advertisement-interval reset */
1429 if (peer_sort (peer) == BGP_PEER_IBGP)
1430 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1431 else
1432 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1433
Paul Jakma0df7c912008-07-21 21:02:49 +00001434 /* password apply */
1435 if (peer->password)
1436 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1437
1438 if (conf->password)
1439 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1440 else
1441 peer->password = NULL;
1442
1443 bgp_md5_set (peer);
1444
paul718e3742002-12-13 20:15:29 +00001445 /* maximum-prefix */
1446 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001447 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001448 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001449
1450 /* allowas-in */
1451 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1452
paulfee0f4c2004-09-13 05:12:46 +00001453 /* route-server-client */
1454 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1455 {
1456 /* Make peer's RIB point to group's RIB. */
1457 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1458
1459 /* Import policy. */
1460 if (pfilter->map[RMAP_IMPORT].name)
1461 free (pfilter->map[RMAP_IMPORT].name);
1462 if (gfilter->map[RMAP_IMPORT].name)
1463 {
1464 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1465 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1466 }
1467 else
1468 {
1469 pfilter->map[RMAP_IMPORT].name = NULL;
1470 pfilter->map[RMAP_IMPORT].map = NULL;
1471 }
1472
1473 /* Export policy. */
1474 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1475 {
1476 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1477 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1478 }
1479 }
1480
paul718e3742002-12-13 20:15:29 +00001481 /* default-originate route-map */
1482 if (conf->default_rmap[afi][safi].name)
1483 {
1484 if (peer->default_rmap[afi][safi].name)
1485 free (peer->default_rmap[afi][safi].name);
1486 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1487 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1488 }
1489
1490 /* update-source apply */
1491 if (conf->update_source)
1492 {
1493 if (peer->update_source)
1494 sockunion_free (peer->update_source);
1495 if (peer->update_if)
1496 {
1497 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1498 peer->update_if = NULL;
1499 }
1500 peer->update_source = sockunion_dup (conf->update_source);
1501 }
1502 else if (conf->update_if)
1503 {
1504 if (peer->update_if)
1505 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1506 if (peer->update_source)
1507 {
1508 sockunion_free (peer->update_source);
1509 peer->update_source = NULL;
1510 }
1511 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1512 }
1513
1514 /* inbound filter apply */
1515 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1516 {
1517 if (pfilter->dlist[in].name)
1518 free (pfilter->dlist[in].name);
1519 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1520 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1521 }
1522 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1523 {
1524 if (pfilter->plist[in].name)
1525 free (pfilter->plist[in].name);
1526 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1527 pfilter->plist[in].plist = gfilter->plist[in].plist;
1528 }
1529 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1530 {
1531 if (pfilter->aslist[in].name)
1532 free (pfilter->aslist[in].name);
1533 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1534 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1535 }
paulfee0f4c2004-09-13 05:12:46 +00001536 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001537 {
paulfee0f4c2004-09-13 05:12:46 +00001538 if (pfilter->map[RMAP_IN].name)
1539 free (pfilter->map[RMAP_IN].name);
1540 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1541 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001542 }
1543
1544 /* outbound filter apply */
1545 if (gfilter->dlist[out].name)
1546 {
1547 if (pfilter->dlist[out].name)
1548 free (pfilter->dlist[out].name);
1549 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1550 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1551 }
1552 else
1553 {
1554 if (pfilter->dlist[out].name)
1555 free (pfilter->dlist[out].name);
1556 pfilter->dlist[out].name = NULL;
1557 pfilter->dlist[out].alist = NULL;
1558 }
1559 if (gfilter->plist[out].name)
1560 {
1561 if (pfilter->plist[out].name)
1562 free (pfilter->plist[out].name);
1563 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1564 pfilter->plist[out].plist = gfilter->plist[out].plist;
1565 }
1566 else
1567 {
1568 if (pfilter->plist[out].name)
1569 free (pfilter->plist[out].name);
1570 pfilter->plist[out].name = NULL;
1571 pfilter->plist[out].plist = NULL;
1572 }
1573 if (gfilter->aslist[out].name)
1574 {
1575 if (pfilter->aslist[out].name)
1576 free (pfilter->aslist[out].name);
1577 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1578 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1579 }
1580 else
1581 {
1582 if (pfilter->aslist[out].name)
1583 free (pfilter->aslist[out].name);
1584 pfilter->aslist[out].name = NULL;
1585 pfilter->aslist[out].aslist = NULL;
1586 }
paulfee0f4c2004-09-13 05:12:46 +00001587 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001588 {
paulfee0f4c2004-09-13 05:12:46 +00001589 if (pfilter->map[RMAP_OUT].name)
1590 free (pfilter->map[RMAP_OUT].name);
1591 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1592 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001593 }
1594 else
1595 {
paulfee0f4c2004-09-13 05:12:46 +00001596 if (pfilter->map[RMAP_OUT].name)
1597 free (pfilter->map[RMAP_OUT].name);
1598 pfilter->map[RMAP_OUT].name = NULL;
1599 pfilter->map[RMAP_OUT].map = NULL;
1600 }
1601
1602 /* RS-client's import/export route-maps. */
1603 if (gfilter->map[RMAP_IMPORT].name)
1604 {
1605 if (pfilter->map[RMAP_IMPORT].name)
1606 free (pfilter->map[RMAP_IMPORT].name);
1607 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1608 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1609 }
1610 else
1611 {
1612 if (pfilter->map[RMAP_IMPORT].name)
1613 free (pfilter->map[RMAP_IMPORT].name);
1614 pfilter->map[RMAP_IMPORT].name = NULL;
1615 pfilter->map[RMAP_IMPORT].map = NULL;
1616 }
1617 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1618 {
1619 if (pfilter->map[RMAP_EXPORT].name)
1620 free (pfilter->map[RMAP_EXPORT].name);
1621 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1622 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001623 }
1624
1625 if (gfilter->usmap.name)
1626 {
1627 if (pfilter->usmap.name)
1628 free (pfilter->usmap.name);
1629 pfilter->usmap.name = strdup (gfilter->usmap.name);
1630 pfilter->usmap.map = gfilter->usmap.map;
1631 }
1632 else
1633 {
1634 if (pfilter->usmap.name)
1635 free (pfilter->usmap.name);
1636 pfilter->usmap.name = NULL;
1637 pfilter->usmap.map = NULL;
1638 }
1639}
1640
1641/* Peer group's remote AS configuration. */
1642int
paulfd79ac92004-10-13 05:06:08 +00001643peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001644{
1645 struct peer_group *group;
1646 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001647 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001648
1649 group = peer_group_lookup (bgp, group_name);
1650 if (! group)
1651 return -1;
1652
1653 if (group->conf->as == *as)
1654 return 0;
1655
1656 /* When we setup peer-group AS number all peer group member's AS
1657 number must be updated to same number. */
1658 peer_as_change (group->conf, *as);
1659
paul1eb8ef22005-04-07 07:30:20 +00001660 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001661 {
1662 if (peer->as != *as)
1663 peer_as_change (peer, *as);
1664 }
1665
1666 return 0;
1667}
1668
1669int
1670peer_group_delete (struct peer_group *group)
1671{
1672 struct bgp *bgp;
1673 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001674 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001675
1676 bgp = group->bgp;
1677
paul1eb8ef22005-04-07 07:30:20 +00001678 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001679 {
1680 peer->group = NULL;
1681 peer_delete (peer);
1682 }
1683 list_delete (group->peer);
1684
1685 free (group->name);
1686 group->name = NULL;
1687
1688 group->conf->group = NULL;
1689 peer_delete (group->conf);
1690
1691 /* Delete from all peer_group list. */
1692 listnode_delete (bgp->group, group);
1693
1694 peer_group_free (group);
1695
1696 return 0;
1697}
1698
1699int
1700peer_group_remote_as_delete (struct peer_group *group)
1701{
1702 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001703 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001704
1705 if (! group->conf->as)
1706 return 0;
1707
paul1eb8ef22005-04-07 07:30:20 +00001708 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001709 {
1710 peer->group = NULL;
1711 peer_delete (peer);
1712 }
1713 list_delete_all_node (group->peer);
1714
1715 group->conf->as = 0;
1716
1717 return 0;
1718}
1719
1720/* Bind specified peer to peer group. */
1721int
1722peer_group_bind (struct bgp *bgp, union sockunion *su,
1723 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1724{
1725 struct peer *peer;
1726 int first_member = 0;
1727
1728 /* Check peer group's address family. */
1729 if (! group->conf->afc[afi][safi])
1730 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1731
1732 /* Lookup the peer. */
1733 peer = peer_lookup (bgp, su);
1734
1735 /* Create a new peer. */
1736 if (! peer)
1737 {
1738 if (! group->conf->as)
1739 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1740
1741 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1742 peer->group = group;
1743 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001744
Paul Jakmaca058a32006-09-14 02:58:49 +00001745 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001746 listnode_add (group->peer, peer);
1747 peer_group2peer_config_copy (group, peer, afi, safi);
1748
1749 return 0;
1750 }
1751
1752 /* When the peer already belongs to peer group, check the consistency. */
1753 if (peer->af_group[afi][safi])
1754 {
1755 if (strcmp (peer->group->name, group->name) != 0)
1756 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1757
1758 return 0;
1759 }
1760
1761 /* Check current peer group configuration. */
1762 if (peer_group_active (peer)
1763 && strcmp (peer->group->name, group->name) != 0)
1764 return BGP_ERR_PEER_GROUP_MISMATCH;
1765
1766 if (! group->conf->as)
1767 {
1768 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1769 && peer_sort (group->conf) != peer_sort (peer))
1770 {
1771 if (as)
1772 *as = peer->as;
1773 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1774 }
1775
1776 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1777 first_member = 1;
1778 }
1779
1780 peer->af_group[afi][safi] = 1;
1781 peer->afc[afi][safi] = 1;
1782 if (! peer->group)
1783 {
1784 peer->group = group;
paul200df112005-06-01 11:17:05 +00001785
Paul Jakmaca058a32006-09-14 02:58:49 +00001786 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001787 listnode_add (group->peer, peer);
1788 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001789 else
1790 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001791
1792 if (first_member)
1793 {
1794 /* Advertisement-interval reset */
1795 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1796 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1797 else
1798 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1799
1800 /* ebgp-multihop reset */
1801 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1802 group->conf->ttl = 255;
1803
1804 /* local-as reset */
1805 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1806 {
1807 group->conf->change_local_as = 0;
1808 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1809 }
1810 }
paulfee0f4c2004-09-13 05:12:46 +00001811
1812 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1813 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001814 struct listnode *pn;
1815
paulfee0f4c2004-09-13 05:12:46 +00001816 /* If it's not configured as RSERVER_CLIENT in any other address
1817 family, without being member of a peer_group, remove it from
1818 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001819 if (! peer_rsclient_active (peer)
1820 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001821 {
1822 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001823 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001824 }
paulfee0f4c2004-09-13 05:12:46 +00001825
Paul Jakmab608d5b2008-07-02 02:12:07 +00001826 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001827
1828 /* Import policy. */
1829 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1830 {
1831 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1832 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1833 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1834 }
1835
1836 /* Export policy. */
1837 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1838 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1839 {
1840 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1841 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1842 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1843 }
1844 }
1845
paul718e3742002-12-13 20:15:29 +00001846 peer_group2peer_config_copy (group, peer, afi, safi);
1847
1848 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001849 {
1850 peer->last_reset = PEER_DOWN_RMAP_BIND;
1851 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1852 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1853 }
paul718e3742002-12-13 20:15:29 +00001854 else
1855 BGP_EVENT_ADD (peer, BGP_Stop);
1856
1857 return 0;
1858}
1859
1860int
1861peer_group_unbind (struct bgp *bgp, struct peer *peer,
1862 struct peer_group *group, afi_t afi, safi_t safi)
1863{
1864 if (! peer->af_group[afi][safi])
1865 return 0;
1866
1867 if (group != peer->group)
1868 return BGP_ERR_PEER_GROUP_MISMATCH;
1869
1870 peer->af_group[afi][safi] = 0;
1871 peer->afc[afi][safi] = 0;
1872 peer_af_flag_reset (peer, afi, safi);
1873
paulfee0f4c2004-09-13 05:12:46 +00001874 if (peer->rib[afi][safi])
1875 peer->rib[afi][safi] = NULL;
1876
paul718e3742002-12-13 20:15:29 +00001877 if (! peer_group_active (peer))
1878 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001879 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001880 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001881 listnode_delete (group->peer, peer);
1882 peer->group = NULL;
1883 if (group->conf->as)
1884 {
1885 peer_delete (peer);
1886 return 0;
1887 }
1888 peer_global_config_reset (peer);
1889 }
1890
1891 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001892 {
1893 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1894 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1895 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1896 }
paul718e3742002-12-13 20:15:29 +00001897 else
1898 BGP_EVENT_ADD (peer, BGP_Stop);
1899
1900 return 0;
1901}
1902
1903/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001904static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001905bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001906{
1907 struct bgp *bgp;
1908 afi_t afi;
1909 safi_t safi;
1910
paul200df112005-06-01 11:17:05 +00001911 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1912 return NULL;
1913
Paul Jakma6f585442006-10-22 19:13:07 +00001914 bgp->peer_self = peer_new (bgp);
paulfd79ac92004-10-13 05:06:08 +00001915 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001916
1917 bgp->peer = list_new ();
1918 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1919
1920 bgp->group = list_new ();
1921 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1922
paulfee0f4c2004-09-13 05:12:46 +00001923 bgp->rsclient = list_new ();
1924 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1925
paul718e3742002-12-13 20:15:29 +00001926 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1927 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1928 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001929 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1930 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1931 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001932 }
1933
1934 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1935 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1936 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001937 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1938 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001939
1940 bgp->as = *as;
1941
1942 if (name)
1943 bgp->name = strdup (name);
1944
1945 return bgp;
1946}
1947
1948/* Return first entry of BGP. */
1949struct bgp *
paul94f2b392005-06-28 12:44:16 +00001950bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001951{
1952 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001953 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001954 return NULL;
1955}
1956
1957/* Lookup BGP entry. */
1958struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001959bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001960{
1961 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001962 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001963
paul1eb8ef22005-04-07 07:30:20 +00001964 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001965 if (bgp->as == as
1966 && ((bgp->name == NULL && name == NULL)
1967 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1968 return bgp;
1969 return NULL;
1970}
1971
1972/* Lookup BGP structure by view name. */
1973struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001974bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001975{
1976 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001977 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001978
paul1eb8ef22005-04-07 07:30:20 +00001979 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001980 if ((bgp->name == NULL && name == NULL)
1981 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1982 return bgp;
1983 return NULL;
1984}
1985
1986/* Called from VTY commands. */
1987int
paulfd79ac92004-10-13 05:06:08 +00001988bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001989{
1990 struct bgp *bgp;
1991
1992 /* Multiple instance check. */
1993 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1994 {
1995 if (name)
1996 bgp = bgp_lookup_by_name (name);
1997 else
1998 bgp = bgp_get_default ();
1999
2000 /* Already exists. */
2001 if (bgp)
2002 {
2003 if (bgp->as != *as)
2004 {
2005 *as = bgp->as;
2006 return BGP_ERR_INSTANCE_MISMATCH;
2007 }
2008 *bgp_val = bgp;
2009 return 0;
2010 }
2011 }
2012 else
2013 {
2014 /* BGP instance name can not be specified for single instance. */
2015 if (name)
2016 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2017
2018 /* Get default BGP structure if exists. */
2019 bgp = bgp_get_default ();
2020
2021 if (bgp)
2022 {
2023 if (bgp->as != *as)
2024 {
2025 *as = bgp->as;
2026 return BGP_ERR_AS_MISMATCH;
2027 }
2028 *bgp_val = bgp;
2029 return 0;
2030 }
2031 }
2032
2033 bgp = bgp_create (as, name);
2034 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002035 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002036 *bgp_val = bgp;
2037
2038 return 0;
2039}
2040
2041/* Delete BGP instance. */
2042int
2043bgp_delete (struct bgp *bgp)
2044{
2045 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002046 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002047 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002048 struct listnode *next;
2049 afi_t afi;
2050 safi_t safi;
2051 int i;
2052
2053 /* Delete static route. */
2054 bgp_static_delete (bgp);
2055
2056 /* Unset redistribution. */
2057 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2058 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2059 if (i != ZEBRA_ROUTE_BGP)
2060 bgp_redistribute_unset (bgp, afi, i);
2061
hassob6b7cff2005-05-26 08:29:07 +00002062 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2063 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002064 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002065
paul1eb8ef22005-04-07 07:30:20 +00002066 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2067 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002068 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002069
hasso54a6ed32005-05-26 22:12:33 +00002070 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2071 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002072 list_delete (bgp->rsclient);
2073
paul718e3742002-12-13 20:15:29 +00002074 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002075
paul718e3742002-12-13 20:15:29 +00002076 if (bgp->name)
2077 free (bgp->name);
2078
2079 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2080 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2081 {
2082 if (bgp->route[afi][safi])
2083 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2084 if (bgp->aggregate[afi][safi])
2085 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2086 if (bgp->rib[afi][safi])
2087 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2088 }
2089 XFREE (MTYPE_BGP, bgp);
2090
2091 return 0;
2092}
2093
2094struct peer *
2095peer_lookup (struct bgp *bgp, union sockunion *su)
2096{
2097 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002098 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002099
2100 if (! bgp)
2101 bgp = bgp_get_default ();
2102
2103 if (! bgp)
2104 return NULL;
2105
paul1eb8ef22005-04-07 07:30:20 +00002106 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002107 {
pauleb821182004-05-01 08:44:08 +00002108 if (sockunion_same (&peer->su, su)
2109 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2110 return peer;
paul718e3742002-12-13 20:15:29 +00002111 }
2112 return NULL;
2113}
2114
2115struct peer *
2116peer_lookup_with_open (union sockunion *su, as_t remote_as,
2117 struct in_addr *remote_id, int *as)
2118{
2119 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002120 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002121 struct bgp *bgp;
2122
2123 bgp = bgp_get_default ();
2124 if (! bgp)
2125 return NULL;
2126
paul1eb8ef22005-04-07 07:30:20 +00002127 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002128 {
pauleb821182004-05-01 08:44:08 +00002129 if (sockunion_same (&peer->su, su)
2130 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2131 {
2132 if (peer->as == remote_as
2133 && peer->remote_id.s_addr == remote_id->s_addr)
2134 return peer;
2135 if (peer->as == remote_as)
2136 *as = 1;
2137 }
paul718e3742002-12-13 20:15:29 +00002138 }
paul1eb8ef22005-04-07 07:30:20 +00002139 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002140 {
pauleb821182004-05-01 08:44:08 +00002141 if (sockunion_same (&peer->su, su)
2142 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2143 {
2144 if (peer->as == remote_as
2145 && peer->remote_id.s_addr == 0)
2146 return peer;
2147 if (peer->as == remote_as)
2148 *as = 1;
2149 }
paul718e3742002-12-13 20:15:29 +00002150 }
2151 return NULL;
2152}
2153
2154/* If peer is configured at least one address family return 1. */
2155int
2156peer_active (struct peer *peer)
2157{
2158 if (peer->afc[AFI_IP][SAFI_UNICAST]
2159 || peer->afc[AFI_IP][SAFI_MULTICAST]
2160 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2161 || peer->afc[AFI_IP6][SAFI_UNICAST]
2162 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2163 return 1;
2164 return 0;
2165}
2166
2167/* If peer is negotiated at least one address family return 1. */
2168int
2169peer_active_nego (struct peer *peer)
2170{
2171 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2172 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2173 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2174 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2175 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2176 return 1;
2177 return 0;
2178}
2179
2180/* peer_flag_change_type. */
2181enum peer_change_type
2182{
2183 peer_change_none,
2184 peer_change_reset,
2185 peer_change_reset_in,
2186 peer_change_reset_out,
2187};
2188
paul94f2b392005-06-28 12:44:16 +00002189static void
paul718e3742002-12-13 20:15:29 +00002190peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2191 enum peer_change_type type)
2192{
2193 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2194 return;
2195
2196 if (type == peer_change_reset)
2197 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2198 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2199 else if (type == peer_change_reset_in)
2200 {
2201 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2202 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2203 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2204 else
2205 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2206 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2207 }
2208 else if (type == peer_change_reset_out)
2209 bgp_announce_route (peer, afi, safi);
2210}
2211
2212struct peer_flag_action
2213{
2214 /* Peer's flag. */
2215 u_int32_t flag;
2216
2217 /* This flag can be set for peer-group member. */
2218 u_char not_for_member;
2219
2220 /* Action when the flag is changed. */
2221 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002222
2223 /* Peer down cause */
2224 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002225};
2226
2227struct peer_flag_action peer_flag_action_list[] =
2228 {
2229 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2230 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2231 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2232 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2233 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002234 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002235 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002236 { 0, 0, 0 }
2237 };
2238
2239struct peer_flag_action peer_af_flag_action_list[] =
2240 {
2241 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2242 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2243 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2244 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2245 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2246 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2247 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2248 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2249 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2250 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2251 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2252 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2253 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002254 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002255 { 0, 0, 0 }
2256 };
2257
2258/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002259static int
paul718e3742002-12-13 20:15:29 +00002260peer_flag_action_set (struct peer_flag_action *action_list, int size,
2261 struct peer_flag_action *action, u_int32_t flag)
2262{
2263 int i;
2264 int found = 0;
2265 int reset_in = 0;
2266 int reset_out = 0;
2267 struct peer_flag_action *match = NULL;
2268
2269 /* Check peer's frag action. */
2270 for (i = 0; i < size; i++)
2271 {
2272 match = &action_list[i];
2273
2274 if (match->flag == 0)
2275 break;
2276
2277 if (match->flag & flag)
2278 {
2279 found = 1;
2280
2281 if (match->type == peer_change_reset_in)
2282 reset_in = 1;
2283 if (match->type == peer_change_reset_out)
2284 reset_out = 1;
2285 if (match->type == peer_change_reset)
2286 {
2287 reset_in = 1;
2288 reset_out = 1;
2289 }
2290 if (match->not_for_member)
2291 action->not_for_member = 1;
2292 }
2293 }
2294
2295 /* Set peer clear type. */
2296 if (reset_in && reset_out)
2297 action->type = peer_change_reset;
2298 else if (reset_in)
2299 action->type = peer_change_reset_in;
2300 else if (reset_out)
2301 action->type = peer_change_reset_out;
2302 else
2303 action->type = peer_change_none;
2304
2305 return found;
2306}
2307
paul94f2b392005-06-28 12:44:16 +00002308static void
paul718e3742002-12-13 20:15:29 +00002309peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2310{
2311 if (flag == PEER_FLAG_SHUTDOWN)
2312 {
2313 if (CHECK_FLAG (peer->flags, flag))
2314 {
hasso93406d82005-02-02 14:40:33 +00002315 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2316 peer_nsf_stop (peer);
2317
hasso0a486e52005-02-01 20:57:17 +00002318 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2319 if (peer->t_pmax_restart)
2320 {
2321 BGP_TIMER_OFF (peer->t_pmax_restart);
2322 if (BGP_DEBUG (events, EVENTS))
2323 zlog_debug ("%s Maximum-prefix restart timer canceled",
2324 peer->host);
2325 }
2326
hasso93406d82005-02-02 14:40:33 +00002327 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2328 peer_nsf_stop (peer);
2329
paul718e3742002-12-13 20:15:29 +00002330 if (peer->status == Established)
2331 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2332 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2333 else
2334 BGP_EVENT_ADD (peer, BGP_Stop);
2335 }
2336 else
2337 {
2338 peer->v_start = BGP_INIT_START_TIMER;
2339 BGP_EVENT_ADD (peer, BGP_Stop);
2340 }
2341 }
2342 else if (peer->status == Established)
2343 {
hassoc9502432005-02-01 22:01:48 +00002344 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2345 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2346 else if (flag == PEER_FLAG_PASSIVE)
2347 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002348 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002349 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002350
hassoc9502432005-02-01 22:01:48 +00002351 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2352 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002353 }
2354 else
2355 BGP_EVENT_ADD (peer, BGP_Stop);
2356}
2357
2358/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002359static int
paul718e3742002-12-13 20:15:29 +00002360peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2361{
2362 int found;
2363 int size;
2364 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002365 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002366 struct peer_flag_action action;
2367
2368 memset (&action, 0, sizeof (struct peer_flag_action));
2369 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2370
2371 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2372
2373 /* No flag action is found. */
2374 if (! found)
2375 return BGP_ERR_INVALID_FLAG;
2376
2377 /* Not for peer-group member. */
2378 if (action.not_for_member && peer_group_active (peer))
2379 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2380
2381 /* When unset the peer-group member's flag we have to check
2382 peer-group configuration. */
2383 if (! set && peer_group_active (peer))
2384 if (CHECK_FLAG (peer->group->conf->flags, flag))
2385 {
2386 if (flag == PEER_FLAG_SHUTDOWN)
2387 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2388 else
2389 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2390 }
2391
2392 /* Flag conflict check. */
2393 if (set
2394 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2395 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2396 return BGP_ERR_PEER_FLAG_CONFLICT;
2397
2398 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2399 {
2400 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2401 return 0;
2402 if (! set && ! CHECK_FLAG (peer->flags, flag))
2403 return 0;
2404 }
2405
2406 if (set)
2407 SET_FLAG (peer->flags, flag);
2408 else
2409 UNSET_FLAG (peer->flags, flag);
2410
2411 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2412 {
2413 if (action.type == peer_change_reset)
2414 peer_flag_modify_action (peer, flag);
2415
2416 return 0;
2417 }
2418
2419 /* peer-group member updates. */
2420 group = peer->group;
2421
paul1eb8ef22005-04-07 07:30:20 +00002422 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002423 {
2424 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2425 continue;
2426
2427 if (! set && ! CHECK_FLAG (peer->flags, flag))
2428 continue;
2429
2430 if (set)
2431 SET_FLAG (peer->flags, flag);
2432 else
2433 UNSET_FLAG (peer->flags, flag);
2434
2435 if (action.type == peer_change_reset)
2436 peer_flag_modify_action (peer, flag);
2437 }
2438 return 0;
2439}
2440
2441int
2442peer_flag_set (struct peer *peer, u_int32_t flag)
2443{
2444 return peer_flag_modify (peer, flag, 1);
2445}
2446
2447int
2448peer_flag_unset (struct peer *peer, u_int32_t flag)
2449{
2450 return peer_flag_modify (peer, flag, 0);
2451}
2452
paul94f2b392005-06-28 12:44:16 +00002453static int
paul718e3742002-12-13 20:15:29 +00002454peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2455{
2456 if (peer->af_group[afi][safi])
2457 return 1;
2458 return 0;
2459}
2460
paul94f2b392005-06-28 12:44:16 +00002461static int
paul718e3742002-12-13 20:15:29 +00002462peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2463 int set)
2464{
2465 int found;
2466 int size;
paul1eb8ef22005-04-07 07:30:20 +00002467 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002468 struct peer_group *group;
2469 struct peer_flag_action action;
2470
2471 memset (&action, 0, sizeof (struct peer_flag_action));
2472 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2473
2474 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2475
2476 /* No flag action is found. */
2477 if (! found)
2478 return BGP_ERR_INVALID_FLAG;
2479
2480 /* Adress family must be activated. */
2481 if (! peer->afc[afi][safi])
2482 return BGP_ERR_PEER_INACTIVE;
2483
2484 /* Not for peer-group member. */
2485 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2486 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2487
2488 /* Spcecial check for reflector client. */
2489 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2490 && peer_sort (peer) != BGP_PEER_IBGP)
2491 return BGP_ERR_NOT_INTERNAL_PEER;
2492
2493 /* Spcecial check for remove-private-AS. */
2494 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2495 && peer_sort (peer) == BGP_PEER_IBGP)
2496 return BGP_ERR_REMOVE_PRIVATE_AS;
2497
2498 /* When unset the peer-group member's flag we have to check
2499 peer-group configuration. */
2500 if (! set && peer->af_group[afi][safi])
2501 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2502 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2503
2504 /* When current flag configuration is same as requested one. */
2505 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2506 {
2507 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2508 return 0;
2509 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2510 return 0;
2511 }
2512
2513 if (set)
2514 SET_FLAG (peer->af_flags[afi][safi], flag);
2515 else
2516 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2517
2518 /* Execute action when peer is established. */
2519 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2520 && peer->status == Established)
2521 {
2522 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2523 bgp_clear_adj_in (peer, afi, safi);
2524 else
hassoe0701b72004-05-20 09:19:34 +00002525 {
2526 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2527 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2528 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2529 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2530 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2531 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2532 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2533 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2534
2535 peer_change_action (peer, afi, safi, action.type);
2536 }
2537
paul718e3742002-12-13 20:15:29 +00002538 }
2539
2540 /* Peer group member updates. */
2541 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2542 {
2543 group = peer->group;
2544
paul1eb8ef22005-04-07 07:30:20 +00002545 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002546 {
2547 if (! peer->af_group[afi][safi])
2548 continue;
2549
2550 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2551 continue;
2552
2553 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2554 continue;
2555
2556 if (set)
2557 SET_FLAG (peer->af_flags[afi][safi], flag);
2558 else
2559 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2560
2561 if (peer->status == Established)
2562 {
2563 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2564 bgp_clear_adj_in (peer, afi, safi);
2565 else
hassoe0701b72004-05-20 09:19:34 +00002566 {
2567 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2568 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2569 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2570 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2571 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2572 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2573 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2574 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2575
2576 peer_change_action (peer, afi, safi, action.type);
2577 }
paul718e3742002-12-13 20:15:29 +00002578 }
2579 }
2580 }
2581 return 0;
2582}
2583
2584int
2585peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2586{
2587 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2588}
2589
2590int
2591peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2592{
2593 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2594}
2595
2596/* EBGP multihop configuration. */
2597int
2598peer_ebgp_multihop_set (struct peer *peer, int ttl)
2599{
2600 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002601 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002602
2603 if (peer_sort (peer) == BGP_PEER_IBGP)
2604 return 0;
2605
2606 peer->ttl = ttl;
2607
2608 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2609 {
pauleb821182004-05-01 08:44:08 +00002610 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2611 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002612 }
2613 else
2614 {
2615 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002616 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002617 {
2618 if (peer_sort (peer) == BGP_PEER_IBGP)
2619 continue;
paul718e3742002-12-13 20:15:29 +00002620
pauleb821182004-05-01 08:44:08 +00002621 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002622
pauleb821182004-05-01 08:44:08 +00002623 if (peer->fd >= 0)
2624 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2625 }
paul718e3742002-12-13 20:15:29 +00002626 }
2627 return 0;
2628}
2629
2630int
2631peer_ebgp_multihop_unset (struct peer *peer)
2632{
2633 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002634 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002635
2636 if (peer_sort (peer) == BGP_PEER_IBGP)
2637 return 0;
2638
2639 if (peer_group_active (peer))
2640 peer->ttl = peer->group->conf->ttl;
2641 else
2642 peer->ttl = 1;
2643
2644 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2645 {
pauleb821182004-05-01 08:44:08 +00002646 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2647 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002648 }
2649 else
2650 {
2651 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002652 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002653 {
2654 if (peer_sort (peer) == BGP_PEER_IBGP)
2655 continue;
paul718e3742002-12-13 20:15:29 +00002656
pauleb821182004-05-01 08:44:08 +00002657 peer->ttl = 1;
2658
2659 if (peer->fd >= 0)
2660 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2661 }
paul718e3742002-12-13 20:15:29 +00002662 }
2663 return 0;
2664}
2665
2666/* Neighbor description. */
2667int
2668peer_description_set (struct peer *peer, char *desc)
2669{
2670 if (peer->desc)
2671 XFREE (MTYPE_PEER_DESC, peer->desc);
2672
2673 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2674
2675 return 0;
2676}
2677
2678int
2679peer_description_unset (struct peer *peer)
2680{
2681 if (peer->desc)
2682 XFREE (MTYPE_PEER_DESC, peer->desc);
2683
2684 peer->desc = NULL;
2685
2686 return 0;
2687}
2688
2689/* Neighbor update-source. */
2690int
paulfd79ac92004-10-13 05:06:08 +00002691peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002692{
2693 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002694 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002695
2696 if (peer->update_if)
2697 {
2698 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2699 && strcmp (peer->update_if, ifname) == 0)
2700 return 0;
2701
2702 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2703 peer->update_if = NULL;
2704 }
2705
2706 if (peer->update_source)
2707 {
2708 sockunion_free (peer->update_source);
2709 peer->update_source = NULL;
2710 }
2711
2712 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2713
2714 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2715 {
2716 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002717 {
2718 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2719 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2720 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2721 }
paul718e3742002-12-13 20:15:29 +00002722 else
2723 BGP_EVENT_ADD (peer, BGP_Stop);
2724 return 0;
2725 }
2726
2727 /* peer-group member updates. */
2728 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002729 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002730 {
2731 if (peer->update_if)
2732 {
2733 if (strcmp (peer->update_if, ifname) == 0)
2734 continue;
2735
2736 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2737 peer->update_if = NULL;
2738 }
2739
2740 if (peer->update_source)
2741 {
2742 sockunion_free (peer->update_source);
2743 peer->update_source = NULL;
2744 }
2745
2746 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2747
2748 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002749 {
2750 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2751 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2752 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2753 }
paul718e3742002-12-13 20:15:29 +00002754 else
2755 BGP_EVENT_ADD (peer, BGP_Stop);
2756 }
2757 return 0;
2758}
2759
2760int
2761peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2762{
2763 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002764 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002765
2766 if (peer->update_source)
2767 {
2768 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2769 && sockunion_cmp (peer->update_source, su) == 0)
2770 return 0;
2771 sockunion_free (peer->update_source);
2772 peer->update_source = NULL;
2773 }
2774
2775 if (peer->update_if)
2776 {
2777 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2778 peer->update_if = NULL;
2779 }
2780
2781 peer->update_source = sockunion_dup (su);
2782
2783 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2784 {
2785 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002786 {
2787 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2788 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2789 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2790 }
paul718e3742002-12-13 20:15:29 +00002791 else
2792 BGP_EVENT_ADD (peer, BGP_Stop);
2793 return 0;
2794 }
2795
2796 /* peer-group member updates. */
2797 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002798 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002799 {
2800 if (peer->update_source)
2801 {
2802 if (sockunion_cmp (peer->update_source, su) == 0)
2803 continue;
2804 sockunion_free (peer->update_source);
2805 peer->update_source = NULL;
2806 }
2807
2808 if (peer->update_if)
2809 {
2810 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2811 peer->update_if = NULL;
2812 }
2813
2814 peer->update_source = sockunion_dup (su);
2815
2816 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002817 {
2818 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2819 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2820 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2821 }
paul718e3742002-12-13 20:15:29 +00002822 else
2823 BGP_EVENT_ADD (peer, BGP_Stop);
2824 }
2825 return 0;
2826}
2827
2828int
2829peer_update_source_unset (struct peer *peer)
2830{
2831 union sockunion *su;
2832 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002833 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002834
2835 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2836 && ! peer->update_source
2837 && ! peer->update_if)
2838 return 0;
2839
2840 if (peer->update_source)
2841 {
2842 sockunion_free (peer->update_source);
2843 peer->update_source = NULL;
2844 }
2845 if (peer->update_if)
2846 {
2847 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2848 peer->update_if = NULL;
2849 }
2850
2851 if (peer_group_active (peer))
2852 {
2853 group = peer->group;
2854
2855 if (group->conf->update_source)
2856 {
2857 su = sockunion_dup (group->conf->update_source);
2858 peer->update_source = su;
2859 }
2860 else if (group->conf->update_if)
2861 peer->update_if =
2862 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2863 }
2864
2865 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2866 {
2867 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002868 {
2869 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2870 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2871 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2872 }
paul718e3742002-12-13 20:15:29 +00002873 else
2874 BGP_EVENT_ADD (peer, BGP_Stop);
2875 return 0;
2876 }
2877
2878 /* peer-group member updates. */
2879 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002880 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002881 {
2882 if (! peer->update_source && ! peer->update_if)
2883 continue;
2884
2885 if (peer->update_source)
2886 {
2887 sockunion_free (peer->update_source);
2888 peer->update_source = NULL;
2889 }
2890
2891 if (peer->update_if)
2892 {
2893 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2894 peer->update_if = NULL;
2895 }
2896
2897 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002898 {
2899 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2900 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2901 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2902 }
paul718e3742002-12-13 20:15:29 +00002903 else
2904 BGP_EVENT_ADD (peer, BGP_Stop);
2905 }
2906 return 0;
2907}
2908
2909int
2910peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002911 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002912{
2913 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002915
2916 /* Adress family must be activated. */
2917 if (! peer->afc[afi][safi])
2918 return BGP_ERR_PEER_INACTIVE;
2919
2920 /* Default originate can't be used for peer group memeber. */
2921 if (peer_is_group_member (peer, afi, safi))
2922 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2923
2924 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2925 || (rmap && ! peer->default_rmap[afi][safi].name)
2926 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2927 {
2928 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2929
2930 if (rmap)
2931 {
2932 if (peer->default_rmap[afi][safi].name)
2933 free (peer->default_rmap[afi][safi].name);
2934 peer->default_rmap[afi][safi].name = strdup (rmap);
2935 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2936 }
2937 }
2938
2939 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2940 {
2941 if (peer->status == Established && peer->afc_nego[afi][safi])
2942 bgp_default_originate (peer, afi, safi, 0);
2943 return 0;
2944 }
2945
2946 /* peer-group member updates. */
2947 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002948 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002949 {
2950 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2951
2952 if (rmap)
2953 {
2954 if (peer->default_rmap[afi][safi].name)
2955 free (peer->default_rmap[afi][safi].name);
2956 peer->default_rmap[afi][safi].name = strdup (rmap);
2957 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2958 }
2959
2960 if (peer->status == Established && peer->afc_nego[afi][safi])
2961 bgp_default_originate (peer, afi, safi, 0);
2962 }
2963 return 0;
2964}
2965
2966int
2967peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2968{
2969 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002970 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002971
2972 /* Adress family must be activated. */
2973 if (! peer->afc[afi][safi])
2974 return BGP_ERR_PEER_INACTIVE;
2975
2976 /* Default originate can't be used for peer group memeber. */
2977 if (peer_is_group_member (peer, afi, safi))
2978 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2979
2980 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2981 {
2982 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2983
2984 if (peer->default_rmap[afi][safi].name)
2985 free (peer->default_rmap[afi][safi].name);
2986 peer->default_rmap[afi][safi].name = NULL;
2987 peer->default_rmap[afi][safi].map = NULL;
2988 }
2989
2990 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2991 {
2992 if (peer->status == Established && peer->afc_nego[afi][safi])
2993 bgp_default_originate (peer, afi, safi, 1);
2994 return 0;
2995 }
2996
2997 /* peer-group member updates. */
2998 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002999 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003000 {
3001 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3002
3003 if (peer->default_rmap[afi][safi].name)
3004 free (peer->default_rmap[afi][safi].name);
3005 peer->default_rmap[afi][safi].name = NULL;
3006 peer->default_rmap[afi][safi].map = NULL;
3007
3008 if (peer->status == Established && peer->afc_nego[afi][safi])
3009 bgp_default_originate (peer, afi, safi, 1);
3010 }
3011 return 0;
3012}
3013
3014int
3015peer_port_set (struct peer *peer, u_int16_t port)
3016{
3017 peer->port = port;
3018 return 0;
3019}
3020
3021int
3022peer_port_unset (struct peer *peer)
3023{
3024 peer->port = BGP_PORT_DEFAULT;
3025 return 0;
3026}
3027
3028/* neighbor weight. */
3029int
3030peer_weight_set (struct peer *peer, u_int16_t weight)
3031{
3032 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003033 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003034
3035 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3036 peer->weight = weight;
3037
3038 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3039 return 0;
3040
3041 /* peer-group member updates. */
3042 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003043 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003044 {
3045 peer->weight = group->conf->weight;
3046 }
3047 return 0;
3048}
3049
3050int
3051peer_weight_unset (struct peer *peer)
3052{
3053 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003054 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003055
3056 /* Set default weight. */
3057 if (peer_group_active (peer))
3058 peer->weight = peer->group->conf->weight;
3059 else
3060 peer->weight = 0;
3061
3062 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3063
3064 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3065 return 0;
3066
3067 /* peer-group member updates. */
3068 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003069 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003070 {
3071 peer->weight = 0;
3072 }
3073 return 0;
3074}
3075
3076int
3077peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3078{
3079 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003080 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003081
3082 /* Not for peer group memeber. */
3083 if (peer_group_active (peer))
3084 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3085
3086 /* keepalive value check. */
3087 if (keepalive > 65535)
3088 return BGP_ERR_INVALID_VALUE;
3089
3090 /* Holdtime value check. */
3091 if (holdtime > 65535)
3092 return BGP_ERR_INVALID_VALUE;
3093
3094 /* Holdtime value must be either 0 or greater than 3. */
3095 if (holdtime < 3 && holdtime != 0)
3096 return BGP_ERR_INVALID_VALUE;
3097
3098 /* Set value to the configuration. */
3099 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3100 peer->holdtime = holdtime;
3101 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3102
3103 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3104 return 0;
3105
3106 /* peer-group member updates. */
3107 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003108 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003109 {
3110 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3111 peer->holdtime = group->conf->holdtime;
3112 peer->keepalive = group->conf->keepalive;
3113 }
3114 return 0;
3115}
3116
3117int
3118peer_timers_unset (struct peer *peer)
3119{
3120 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003121 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003122
3123 if (peer_group_active (peer))
3124 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3125
3126 /* Clear configuration. */
3127 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3128 peer->keepalive = 0;
3129 peer->holdtime = 0;
3130
3131 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3132 return 0;
3133
3134 /* peer-group member updates. */
3135 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003136 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003137 {
3138 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3139 peer->holdtime = 0;
3140 peer->keepalive = 0;
3141 }
3142
3143 return 0;
3144}
3145
3146int
3147peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3148{
3149 if (peer_group_active (peer))
3150 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3151
3152 if (connect > 65535)
3153 return BGP_ERR_INVALID_VALUE;
3154
3155 /* Set value to the configuration. */
3156 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3157 peer->connect = connect;
3158
3159 /* Set value to timer setting. */
3160 peer->v_connect = connect;
3161
3162 return 0;
3163}
3164
3165int
3166peer_timers_connect_unset (struct peer *peer)
3167{
3168 if (peer_group_active (peer))
3169 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3170
3171 /* Clear configuration. */
3172 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3173 peer->connect = 0;
3174
3175 /* Set timer setting to default value. */
3176 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3177
3178 return 0;
3179}
3180
3181int
3182peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3183{
3184 if (peer_group_active (peer))
3185 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3186
3187 if (routeadv > 600)
3188 return BGP_ERR_INVALID_VALUE;
3189
3190 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3191 peer->routeadv = routeadv;
3192 peer->v_routeadv = routeadv;
3193
3194 return 0;
3195}
3196
3197int
3198peer_advertise_interval_unset (struct peer *peer)
3199{
3200 if (peer_group_active (peer))
3201 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3202
3203 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3204 peer->routeadv = 0;
3205
3206 if (peer_sort (peer) == BGP_PEER_IBGP)
3207 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3208 else
3209 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3210
3211 return 0;
3212}
3213
paul718e3742002-12-13 20:15:29 +00003214/* neighbor interface */
3215int
paulfd79ac92004-10-13 05:06:08 +00003216peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003217{
3218 if (peer->ifname)
3219 free (peer->ifname);
3220 peer->ifname = strdup (str);
3221
3222 return 0;
3223}
3224
3225int
3226peer_interface_unset (struct peer *peer)
3227{
3228 if (peer->ifname)
3229 free (peer->ifname);
3230 peer->ifname = NULL;
3231
3232 return 0;
3233}
3234
3235/* Allow-as in. */
3236int
3237peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3238{
3239 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003240 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003241
3242 if (allow_num < 1 || allow_num > 10)
3243 return BGP_ERR_INVALID_VALUE;
3244
3245 if (peer->allowas_in[afi][safi] != allow_num)
3246 {
3247 peer->allowas_in[afi][safi] = allow_num;
3248 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3249 peer_change_action (peer, afi, safi, peer_change_reset_in);
3250 }
3251
3252 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3253 return 0;
3254
3255 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003256 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003257 {
3258 if (peer->allowas_in[afi][safi] != allow_num)
3259 {
3260 peer->allowas_in[afi][safi] = allow_num;
3261 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3262 peer_change_action (peer, afi, safi, peer_change_reset_in);
3263 }
3264
3265 }
3266 return 0;
3267}
3268
3269int
3270peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3271{
3272 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003273 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003274
3275 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3276 {
3277 peer->allowas_in[afi][safi] = 0;
3278 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3279 }
3280
3281 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3282 return 0;
3283
3284 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003285 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003286 {
3287 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3288 {
3289 peer->allowas_in[afi][safi] = 0;
3290 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3291 }
3292 }
3293 return 0;
3294}
3295
3296int
3297peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3298{
3299 struct bgp *bgp = peer->bgp;
3300 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003301 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003302
3303 if (peer_sort (peer) != BGP_PEER_EBGP
3304 && peer_sort (peer) != BGP_PEER_INTERNAL)
3305 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3306
3307 if (bgp->as == as)
3308 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3309
3310 if (peer_group_active (peer))
3311 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3312
3313 if (peer->change_local_as == as &&
3314 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3315 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3316 return 0;
3317
3318 peer->change_local_as = as;
3319 if (no_prepend)
3320 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3321 else
3322 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3323
3324 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3325 {
3326 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003327 {
3328 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3329 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3330 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3331 }
paul718e3742002-12-13 20:15:29 +00003332 else
3333 BGP_EVENT_ADD (peer, BGP_Stop);
3334
3335 return 0;
3336 }
3337
3338 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003339 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003340 {
3341 peer->change_local_as = as;
3342 if (no_prepend)
3343 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3344 else
3345 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3346
3347 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003348 {
3349 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3350 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3351 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3352 }
paul718e3742002-12-13 20:15:29 +00003353 else
3354 BGP_EVENT_ADD (peer, BGP_Stop);
3355 }
3356
3357 return 0;
3358}
3359
3360int
3361peer_local_as_unset (struct peer *peer)
3362{
3363 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003364 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003365
3366 if (peer_group_active (peer))
3367 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3368
3369 if (! peer->change_local_as)
3370 return 0;
3371
3372 peer->change_local_as = 0;
3373 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3374
3375 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3376 {
3377 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003378 {
3379 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3380 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3381 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3382 }
paul718e3742002-12-13 20:15:29 +00003383 else
3384 BGP_EVENT_ADD (peer, BGP_Stop);
3385
3386 return 0;
3387 }
3388
3389 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003390 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003391 {
3392 peer->change_local_as = 0;
3393 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3394
3395 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003396 {
3397 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3398 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3399 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3400 }
paul718e3742002-12-13 20:15:29 +00003401 else
3402 BGP_EVENT_ADD (peer, BGP_Stop);
3403 }
3404 return 0;
3405}
3406
Paul Jakma0df7c912008-07-21 21:02:49 +00003407/* Set password for authenticating with the peer. */
3408int
3409peer_password_set (struct peer *peer, const char *password)
3410{
3411 struct listnode *nn, *nnode;
3412 int len = password ? strlen(password) : 0;
3413 int ret = BGP_SUCCESS;
3414
3415 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3416 return BGP_ERR_INVALID_VALUE;
3417
3418 if (peer->password && strcmp (peer->password, password) == 0
3419 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3420 return 0;
3421
3422 if (peer->password)
3423 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3424
3425 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3426
3427 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3428 {
3429 if (peer->status == Established)
3430 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3431 else
3432 BGP_EVENT_ADD (peer, BGP_Stop);
3433
3434 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3435 }
3436
3437 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3438 {
3439 if (peer->password && strcmp (peer->password, password) == 0)
3440 continue;
3441
3442 if (peer->password)
3443 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3444
3445 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3446
3447 if (peer->status == Established)
3448 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3449 else
3450 BGP_EVENT_ADD (peer, BGP_Stop);
3451
3452 if (bgp_md5_set (peer) < 0)
3453 ret = BGP_ERR_TCPSIG_FAILED;
3454 }
3455
3456 return ret;
3457}
3458
3459int
3460peer_password_unset (struct peer *peer)
3461{
3462 struct listnode *nn, *nnode;
3463
3464 if (!peer->password
3465 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3466 return 0;
3467
3468 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3469 {
3470 if (peer_group_active (peer)
3471 && peer->group->conf->password
3472 && strcmp (peer->group->conf->password, peer->password) == 0)
3473 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3474
3475 if (peer->status == Established)
3476 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3477 else
3478 BGP_EVENT_ADD (peer, BGP_Stop);
3479
3480 if (peer->password)
3481 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3482
3483 peer->password = NULL;
3484
3485 bgp_md5_set (peer);
3486
3487 return 0;
3488 }
3489
3490 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3491 peer->password = NULL;
3492
3493 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3494 {
3495 if (!peer->password)
3496 continue;
3497
3498 if (peer->status == Established)
3499 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3500 else
3501 BGP_EVENT_ADD (peer, BGP_Stop);
3502
3503 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3504 peer->password = NULL;
3505
3506 bgp_md5_set (peer);
3507 }
3508
3509 return 0;
3510}
3511
paul718e3742002-12-13 20:15:29 +00003512/* Set distribute list to the peer. */
3513int
3514peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003515 const char *name)
paul718e3742002-12-13 20:15:29 +00003516{
3517 struct bgp_filter *filter;
3518 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003519 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003520
3521 if (! peer->afc[afi][safi])
3522 return BGP_ERR_PEER_INACTIVE;
3523
3524 if (direct != FILTER_IN && direct != FILTER_OUT)
3525 return BGP_ERR_INVALID_VALUE;
3526
3527 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3528 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3529
3530 filter = &peer->filter[afi][safi];
3531
3532 if (filter->plist[direct].name)
3533 return BGP_ERR_PEER_FILTER_CONFLICT;
3534
3535 if (filter->dlist[direct].name)
3536 free (filter->dlist[direct].name);
3537 filter->dlist[direct].name = strdup (name);
3538 filter->dlist[direct].alist = access_list_lookup (afi, name);
3539
3540 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3541 return 0;
3542
3543 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003544 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003545 {
3546 filter = &peer->filter[afi][safi];
3547
3548 if (! peer->af_group[afi][safi])
3549 continue;
3550
3551 if (filter->dlist[direct].name)
3552 free (filter->dlist[direct].name);
3553 filter->dlist[direct].name = strdup (name);
3554 filter->dlist[direct].alist = access_list_lookup (afi, name);
3555 }
3556
3557 return 0;
3558}
3559
3560int
3561peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3562{
3563 struct bgp_filter *filter;
3564 struct bgp_filter *gfilter;
3565 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003566 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003567
3568 if (! peer->afc[afi][safi])
3569 return BGP_ERR_PEER_INACTIVE;
3570
3571 if (direct != FILTER_IN && direct != FILTER_OUT)
3572 return BGP_ERR_INVALID_VALUE;
3573
3574 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3575 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3576
3577 filter = &peer->filter[afi][safi];
3578
3579 /* apply peer-group filter */
3580 if (peer->af_group[afi][safi])
3581 {
3582 gfilter = &peer->group->conf->filter[afi][safi];
3583
3584 if (gfilter->dlist[direct].name)
3585 {
3586 if (filter->dlist[direct].name)
3587 free (filter->dlist[direct].name);
3588 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3589 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3590 return 0;
3591 }
3592 }
3593
3594 if (filter->dlist[direct].name)
3595 free (filter->dlist[direct].name);
3596 filter->dlist[direct].name = NULL;
3597 filter->dlist[direct].alist = NULL;
3598
3599 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3600 return 0;
3601
3602 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003603 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003604 {
3605 filter = &peer->filter[afi][safi];
3606
3607 if (! peer->af_group[afi][safi])
3608 continue;
3609
3610 if (filter->dlist[direct].name)
3611 free (filter->dlist[direct].name);
3612 filter->dlist[direct].name = NULL;
3613 filter->dlist[direct].alist = NULL;
3614 }
3615
3616 return 0;
3617}
3618
3619/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003620static void
paul718e3742002-12-13 20:15:29 +00003621peer_distribute_update (struct access_list *access)
3622{
3623 afi_t afi;
3624 safi_t safi;
3625 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003626 struct listnode *mnode, *mnnode;
3627 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003628 struct bgp *bgp;
3629 struct peer *peer;
3630 struct peer_group *group;
3631 struct bgp_filter *filter;
3632
paul1eb8ef22005-04-07 07:30:20 +00003633 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003634 {
paul1eb8ef22005-04-07 07:30:20 +00003635 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003636 {
3637 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3638 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3639 {
3640 filter = &peer->filter[afi][safi];
3641
3642 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3643 {
3644 if (filter->dlist[direct].name)
3645 filter->dlist[direct].alist =
3646 access_list_lookup (afi, filter->dlist[direct].name);
3647 else
3648 filter->dlist[direct].alist = NULL;
3649 }
3650 }
3651 }
paul1eb8ef22005-04-07 07:30:20 +00003652 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003653 {
3654 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3655 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3656 {
3657 filter = &group->conf->filter[afi][safi];
3658
3659 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3660 {
3661 if (filter->dlist[direct].name)
3662 filter->dlist[direct].alist =
3663 access_list_lookup (afi, filter->dlist[direct].name);
3664 else
3665 filter->dlist[direct].alist = NULL;
3666 }
3667 }
3668 }
3669 }
3670}
3671
3672/* Set prefix list to the peer. */
3673int
3674peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003675 const char *name)
paul718e3742002-12-13 20:15:29 +00003676{
3677 struct bgp_filter *filter;
3678 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003679 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003680
3681 if (! peer->afc[afi][safi])
3682 return BGP_ERR_PEER_INACTIVE;
3683
3684 if (direct != FILTER_IN && direct != FILTER_OUT)
3685 return BGP_ERR_INVALID_VALUE;
3686
3687 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3688 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3689
3690 filter = &peer->filter[afi][safi];
3691
3692 if (filter->dlist[direct].name)
3693 return BGP_ERR_PEER_FILTER_CONFLICT;
3694
3695 if (filter->plist[direct].name)
3696 free (filter->plist[direct].name);
3697 filter->plist[direct].name = strdup (name);
3698 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3699
3700 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3701 return 0;
3702
3703 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003704 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003705 {
3706 filter = &peer->filter[afi][safi];
3707
3708 if (! peer->af_group[afi][safi])
3709 continue;
3710
3711 if (filter->plist[direct].name)
3712 free (filter->plist[direct].name);
3713 filter->plist[direct].name = strdup (name);
3714 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3715 }
3716 return 0;
3717}
3718
3719int
3720peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3721{
3722 struct bgp_filter *filter;
3723 struct bgp_filter *gfilter;
3724 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003725 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003726
3727 if (! peer->afc[afi][safi])
3728 return BGP_ERR_PEER_INACTIVE;
3729
3730 if (direct != FILTER_IN && direct != FILTER_OUT)
3731 return BGP_ERR_INVALID_VALUE;
3732
3733 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3734 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3735
3736 filter = &peer->filter[afi][safi];
3737
3738 /* apply peer-group filter */
3739 if (peer->af_group[afi][safi])
3740 {
3741 gfilter = &peer->group->conf->filter[afi][safi];
3742
3743 if (gfilter->plist[direct].name)
3744 {
3745 if (filter->plist[direct].name)
3746 free (filter->plist[direct].name);
3747 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3748 filter->plist[direct].plist = gfilter->plist[direct].plist;
3749 return 0;
3750 }
3751 }
3752
3753 if (filter->plist[direct].name)
3754 free (filter->plist[direct].name);
3755 filter->plist[direct].name = NULL;
3756 filter->plist[direct].plist = NULL;
3757
3758 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3759 return 0;
3760
3761 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003762 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003763 {
3764 filter = &peer->filter[afi][safi];
3765
3766 if (! peer->af_group[afi][safi])
3767 continue;
3768
3769 if (filter->plist[direct].name)
3770 free (filter->plist[direct].name);
3771 filter->plist[direct].name = NULL;
3772 filter->plist[direct].plist = NULL;
3773 }
3774
3775 return 0;
3776}
3777
3778/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003779static void
paul718e3742002-12-13 20:15:29 +00003780peer_prefix_list_update (struct prefix_list *plist)
3781{
paul1eb8ef22005-04-07 07:30:20 +00003782 struct listnode *mnode, *mnnode;
3783 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003784 struct bgp *bgp;
3785 struct peer *peer;
3786 struct peer_group *group;
3787 struct bgp_filter *filter;
3788 afi_t afi;
3789 safi_t safi;
3790 int direct;
3791
paul1eb8ef22005-04-07 07:30:20 +00003792 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003793 {
paul1eb8ef22005-04-07 07:30:20 +00003794 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003795 {
3796 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3797 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3798 {
3799 filter = &peer->filter[afi][safi];
3800
3801 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3802 {
3803 if (filter->plist[direct].name)
3804 filter->plist[direct].plist =
3805 prefix_list_lookup (afi, filter->plist[direct].name);
3806 else
3807 filter->plist[direct].plist = NULL;
3808 }
3809 }
3810 }
paul1eb8ef22005-04-07 07:30:20 +00003811 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003812 {
3813 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3814 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3815 {
3816 filter = &group->conf->filter[afi][safi];
3817
3818 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3819 {
3820 if (filter->plist[direct].name)
3821 filter->plist[direct].plist =
3822 prefix_list_lookup (afi, filter->plist[direct].name);
3823 else
3824 filter->plist[direct].plist = NULL;
3825 }
3826 }
3827 }
3828 }
3829}
3830
3831int
3832peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003833 const char *name)
paul718e3742002-12-13 20:15:29 +00003834{
3835 struct bgp_filter *filter;
3836 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003837 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003838
3839 if (! peer->afc[afi][safi])
3840 return BGP_ERR_PEER_INACTIVE;
3841
3842 if (direct != FILTER_IN && direct != FILTER_OUT)
3843 return BGP_ERR_INVALID_VALUE;
3844
3845 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3846 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3847
3848 filter = &peer->filter[afi][safi];
3849
3850 if (filter->aslist[direct].name)
3851 free (filter->aslist[direct].name);
3852 filter->aslist[direct].name = strdup (name);
3853 filter->aslist[direct].aslist = as_list_lookup (name);
3854
3855 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3856 return 0;
3857
3858 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003859 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003860 {
3861 filter = &peer->filter[afi][safi];
3862
3863 if (! peer->af_group[afi][safi])
3864 continue;
3865
3866 if (filter->aslist[direct].name)
3867 free (filter->aslist[direct].name);
3868 filter->aslist[direct].name = strdup (name);
3869 filter->aslist[direct].aslist = as_list_lookup (name);
3870 }
3871 return 0;
3872}
3873
3874int
3875peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3876{
3877 struct bgp_filter *filter;
3878 struct bgp_filter *gfilter;
3879 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003880 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003881
3882 if (! peer->afc[afi][safi])
3883 return BGP_ERR_PEER_INACTIVE;
3884
hassob5f29602005-05-25 21:00:28 +00003885 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003886 return BGP_ERR_INVALID_VALUE;
3887
hassob5f29602005-05-25 21:00:28 +00003888 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003889 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3890
3891 filter = &peer->filter[afi][safi];
3892
3893 /* apply peer-group filter */
3894 if (peer->af_group[afi][safi])
3895 {
3896 gfilter = &peer->group->conf->filter[afi][safi];
3897
3898 if (gfilter->aslist[direct].name)
3899 {
3900 if (filter->aslist[direct].name)
3901 free (filter->aslist[direct].name);
3902 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3903 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3904 return 0;
3905 }
3906 }
3907
3908 if (filter->aslist[direct].name)
3909 free (filter->aslist[direct].name);
3910 filter->aslist[direct].name = NULL;
3911 filter->aslist[direct].aslist = NULL;
3912
3913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3914 return 0;
3915
3916 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003917 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003918 {
3919 filter = &peer->filter[afi][safi];
3920
3921 if (! peer->af_group[afi][safi])
3922 continue;
3923
3924 if (filter->aslist[direct].name)
3925 free (filter->aslist[direct].name);
3926 filter->aslist[direct].name = NULL;
3927 filter->aslist[direct].aslist = NULL;
3928 }
3929
3930 return 0;
3931}
3932
paul94f2b392005-06-28 12:44:16 +00003933static void
paul718e3742002-12-13 20:15:29 +00003934peer_aslist_update ()
3935{
3936 afi_t afi;
3937 safi_t safi;
3938 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003939 struct listnode *mnode, *mnnode;
3940 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003941 struct bgp *bgp;
3942 struct peer *peer;
3943 struct peer_group *group;
3944 struct bgp_filter *filter;
3945
paul1eb8ef22005-04-07 07:30:20 +00003946 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003947 {
paul1eb8ef22005-04-07 07:30:20 +00003948 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003949 {
3950 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3951 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3952 {
3953 filter = &peer->filter[afi][safi];
3954
3955 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3956 {
3957 if (filter->aslist[direct].name)
3958 filter->aslist[direct].aslist =
3959 as_list_lookup (filter->aslist[direct].name);
3960 else
3961 filter->aslist[direct].aslist = NULL;
3962 }
3963 }
3964 }
paul1eb8ef22005-04-07 07:30:20 +00003965 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003966 {
3967 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3968 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3969 {
3970 filter = &group->conf->filter[afi][safi];
3971
3972 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3973 {
3974 if (filter->aslist[direct].name)
3975 filter->aslist[direct].aslist =
3976 as_list_lookup (filter->aslist[direct].name);
3977 else
3978 filter->aslist[direct].aslist = NULL;
3979 }
3980 }
3981 }
3982 }
3983}
3984
3985/* Set route-map to the peer. */
3986int
3987peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003988 const char *name)
paul718e3742002-12-13 20:15:29 +00003989{
3990 struct bgp_filter *filter;
3991 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003992 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003993
3994 if (! peer->afc[afi][safi])
3995 return BGP_ERR_PEER_INACTIVE;
3996
paulfee0f4c2004-09-13 05:12:46 +00003997 if (direct != RMAP_IN && direct != RMAP_OUT &&
3998 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003999 return BGP_ERR_INVALID_VALUE;
4000
paulfee0f4c2004-09-13 05:12:46 +00004001 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4002 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004003 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4004
4005 filter = &peer->filter[afi][safi];
4006
4007 if (filter->map[direct].name)
4008 free (filter->map[direct].name);
4009
4010 filter->map[direct].name = strdup (name);
4011 filter->map[direct].map = route_map_lookup_by_name (name);
4012
4013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4014 return 0;
4015
4016 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004017 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004018 {
4019 filter = &peer->filter[afi][safi];
4020
4021 if (! peer->af_group[afi][safi])
4022 continue;
4023
4024 if (filter->map[direct].name)
4025 free (filter->map[direct].name);
4026 filter->map[direct].name = strdup (name);
4027 filter->map[direct].map = route_map_lookup_by_name (name);
4028 }
4029 return 0;
4030}
4031
4032/* Unset route-map from the peer. */
4033int
4034peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4035{
4036 struct bgp_filter *filter;
4037 struct bgp_filter *gfilter;
4038 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004039 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004040
4041 if (! peer->afc[afi][safi])
4042 return BGP_ERR_PEER_INACTIVE;
4043
hassob5f29602005-05-25 21:00:28 +00004044 if (direct != RMAP_IN && direct != RMAP_OUT &&
4045 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004046 return BGP_ERR_INVALID_VALUE;
4047
hassob5f29602005-05-25 21:00:28 +00004048 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4049 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004050 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4051
4052 filter = &peer->filter[afi][safi];
4053
4054 /* apply peer-group filter */
4055 if (peer->af_group[afi][safi])
4056 {
4057 gfilter = &peer->group->conf->filter[afi][safi];
4058
4059 if (gfilter->map[direct].name)
4060 {
4061 if (filter->map[direct].name)
4062 free (filter->map[direct].name);
4063 filter->map[direct].name = strdup (gfilter->map[direct].name);
4064 filter->map[direct].map = gfilter->map[direct].map;
4065 return 0;
4066 }
4067 }
4068
4069 if (filter->map[direct].name)
4070 free (filter->map[direct].name);
4071 filter->map[direct].name = NULL;
4072 filter->map[direct].map = NULL;
4073
4074 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4075 return 0;
4076
4077 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004079 {
4080 filter = &peer->filter[afi][safi];
4081
4082 if (! peer->af_group[afi][safi])
4083 continue;
4084
4085 if (filter->map[direct].name)
4086 free (filter->map[direct].name);
4087 filter->map[direct].name = NULL;
4088 filter->map[direct].map = NULL;
4089 }
4090 return 0;
4091}
4092
4093/* Set unsuppress-map to the peer. */
4094int
paulfd79ac92004-10-13 05:06:08 +00004095peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4096 const char *name)
paul718e3742002-12-13 20:15:29 +00004097{
4098 struct bgp_filter *filter;
4099 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004100 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004101
4102 if (! peer->afc[afi][safi])
4103 return BGP_ERR_PEER_INACTIVE;
4104
4105 if (peer_is_group_member (peer, afi, safi))
4106 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4107
4108 filter = &peer->filter[afi][safi];
4109
4110 if (filter->usmap.name)
4111 free (filter->usmap.name);
4112
4113 filter->usmap.name = strdup (name);
4114 filter->usmap.map = route_map_lookup_by_name (name);
4115
4116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4117 return 0;
4118
4119 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004120 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004121 {
4122 filter = &peer->filter[afi][safi];
4123
4124 if (! peer->af_group[afi][safi])
4125 continue;
4126
4127 if (filter->usmap.name)
4128 free (filter->usmap.name);
4129 filter->usmap.name = strdup (name);
4130 filter->usmap.map = route_map_lookup_by_name (name);
4131 }
4132 return 0;
4133}
4134
4135/* Unset route-map from the peer. */
4136int
4137peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4138{
4139 struct bgp_filter *filter;
4140 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004141 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004142
4143 if (! peer->afc[afi][safi])
4144 return BGP_ERR_PEER_INACTIVE;
4145
4146 if (peer_is_group_member (peer, afi, safi))
4147 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4148
4149 filter = &peer->filter[afi][safi];
4150
4151 if (filter->usmap.name)
4152 free (filter->usmap.name);
4153 filter->usmap.name = NULL;
4154 filter->usmap.map = NULL;
4155
4156 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4157 return 0;
4158
4159 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004160 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004161 {
4162 filter = &peer->filter[afi][safi];
4163
4164 if (! peer->af_group[afi][safi])
4165 continue;
4166
4167 if (filter->usmap.name)
4168 free (filter->usmap.name);
4169 filter->usmap.name = NULL;
4170 filter->usmap.map = NULL;
4171 }
4172 return 0;
4173}
4174
4175int
4176peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004177 u_int32_t max, u_char threshold,
4178 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004179{
4180 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004181 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004182
4183 if (! peer->afc[afi][safi])
4184 return BGP_ERR_PEER_INACTIVE;
4185
4186 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4187 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004188 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004189 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004190 if (warning)
4191 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4192 else
4193 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4194
4195 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4196 return 0;
4197
4198 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004199 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004200 {
4201 if (! peer->af_group[afi][safi])
4202 continue;
4203
4204 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4205 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004206 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004207 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004208 if (warning)
4209 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4210 else
4211 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4212 }
4213 return 0;
4214}
4215
4216int
4217peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4218{
4219 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004220 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004221
4222 if (! peer->afc[afi][safi])
4223 return BGP_ERR_PEER_INACTIVE;
4224
4225 /* apply peer-group config */
4226 if (peer->af_group[afi][safi])
4227 {
4228 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4229 PEER_FLAG_MAX_PREFIX))
4230 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4231 else
4232 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4233
4234 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4235 PEER_FLAG_MAX_PREFIX_WARNING))
4236 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4237 else
4238 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4239
4240 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004241 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004242 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004243 return 0;
4244 }
4245
4246 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4247 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4248 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004249 peer->pmax_threshold[afi][safi] = 0;
4250 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004251
4252 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4253 return 0;
4254
4255 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004256 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004257 {
4258 if (! peer->af_group[afi][safi])
4259 continue;
4260
4261 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4262 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4263 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004264 peer->pmax_threshold[afi][safi] = 0;
4265 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004266 }
4267 return 0;
4268}
4269
4270int
4271peer_clear (struct peer *peer)
4272{
4273 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4274 {
hasso0a486e52005-02-01 20:57:17 +00004275 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4276 {
4277 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4278 if (peer->t_pmax_restart)
4279 {
4280 BGP_TIMER_OFF (peer->t_pmax_restart);
4281 if (BGP_DEBUG (events, EVENTS))
4282 zlog_debug ("%s Maximum-prefix restart timer canceled",
4283 peer->host);
4284 }
4285 BGP_EVENT_ADD (peer, BGP_Start);
4286 return 0;
4287 }
4288
paul718e3742002-12-13 20:15:29 +00004289 peer->v_start = BGP_INIT_START_TIMER;
4290 if (peer->status == Established)
4291 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4292 BGP_NOTIFY_CEASE_ADMIN_RESET);
4293 else
4294 BGP_EVENT_ADD (peer, BGP_Stop);
4295 }
4296 return 0;
4297}
4298
4299int
4300peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4301 enum bgp_clear_type stype)
4302{
4303 if (peer->status != Established)
4304 return 0;
4305
4306 if (! peer->afc[afi][safi])
4307 return BGP_ERR_AF_UNCONFIGURED;
4308
paulfee0f4c2004-09-13 05:12:46 +00004309 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4310 {
4311 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4312 return 0;
4313 bgp_check_local_routes_rsclient (peer, afi, safi);
4314 bgp_soft_reconfig_rsclient (peer, afi, safi);
4315 }
4316
paul718e3742002-12-13 20:15:29 +00004317 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4318 bgp_announce_route (peer, afi, safi);
4319
4320 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4321 {
4322 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4323 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4324 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4325 {
4326 struct bgp_filter *filter = &peer->filter[afi][safi];
4327 u_char prefix_type;
4328
4329 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4330 prefix_type = ORF_TYPE_PREFIX;
4331 else
4332 prefix_type = ORF_TYPE_PREFIX_OLD;
4333
4334 if (filter->plist[FILTER_IN].plist)
4335 {
4336 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4337 bgp_route_refresh_send (peer, afi, safi,
4338 prefix_type, REFRESH_DEFER, 1);
4339 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4340 REFRESH_IMMEDIATE, 0);
4341 }
4342 else
4343 {
4344 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4345 bgp_route_refresh_send (peer, afi, safi,
4346 prefix_type, REFRESH_IMMEDIATE, 1);
4347 else
4348 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4349 }
4350 return 0;
4351 }
4352 }
4353
4354 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4355 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4356 {
4357 /* If neighbor has soft reconfiguration inbound flag.
4358 Use Adj-RIB-In database. */
4359 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4360 bgp_soft_reconfig_in (peer, afi, safi);
4361 else
4362 {
4363 /* If neighbor has route refresh capability, send route refresh
4364 message to the peer. */
4365 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4366 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4367 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4368 else
4369 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4370 }
4371 }
4372 return 0;
4373}
4374
paulfd79ac92004-10-13 05:06:08 +00004375/* Display peer uptime.*/
4376/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004377char *
4378peer_uptime (time_t uptime2, char *buf, size_t len)
4379{
4380 time_t uptime1;
4381 struct tm *tm;
4382
4383 /* Check buffer length. */
4384 if (len < BGP_UPTIME_LEN)
4385 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004386 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004387 /* XXX: should return status instead of buf... */
4388 snprintf (buf, len, "<error> ");
4389 return buf;
paul718e3742002-12-13 20:15:29 +00004390 }
4391
4392 /* If there is no connection has been done before print `never'. */
4393 if (uptime2 == 0)
4394 {
4395 snprintf (buf, len, "never ");
4396 return buf;
4397 }
4398
4399 /* Get current time. */
4400 uptime1 = time (NULL);
4401 uptime1 -= uptime2;
4402 tm = gmtime (&uptime1);
4403
4404 /* Making formatted timer strings. */
4405#define ONE_DAY_SECOND 60*60*24
4406#define ONE_WEEK_SECOND 60*60*24*7
4407
4408 if (uptime1 < ONE_DAY_SECOND)
4409 snprintf (buf, len, "%02d:%02d:%02d",
4410 tm->tm_hour, tm->tm_min, tm->tm_sec);
4411 else if (uptime1 < ONE_WEEK_SECOND)
4412 snprintf (buf, len, "%dd%02dh%02dm",
4413 tm->tm_yday, tm->tm_hour, tm->tm_min);
4414 else
4415 snprintf (buf, len, "%02dw%dd%02dh",
4416 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4417 return buf;
4418}
4419
paul94f2b392005-06-28 12:44:16 +00004420static void
paul718e3742002-12-13 20:15:29 +00004421bgp_config_write_filter (struct vty *vty, struct peer *peer,
4422 afi_t afi, safi_t safi)
4423{
4424 struct bgp_filter *filter;
4425 struct bgp_filter *gfilter = NULL;
4426 char *addr;
4427 int in = FILTER_IN;
4428 int out = FILTER_OUT;
4429
4430 addr = peer->host;
4431 filter = &peer->filter[afi][safi];
4432 if (peer->af_group[afi][safi])
4433 gfilter = &peer->group->conf->filter[afi][safi];
4434
4435 /* distribute-list. */
4436 if (filter->dlist[in].name)
4437 if (! gfilter || ! gfilter->dlist[in].name
4438 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4439 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4440 filter->dlist[in].name, VTY_NEWLINE);
4441 if (filter->dlist[out].name && ! gfilter)
4442 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4443 filter->dlist[out].name, VTY_NEWLINE);
4444
4445 /* prefix-list. */
4446 if (filter->plist[in].name)
4447 if (! gfilter || ! gfilter->plist[in].name
4448 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4449 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4450 filter->plist[in].name, VTY_NEWLINE);
4451 if (filter->plist[out].name && ! gfilter)
4452 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4453 filter->plist[out].name, VTY_NEWLINE);
4454
4455 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004456 if (filter->map[RMAP_IN].name)
4457 if (! gfilter || ! gfilter->map[RMAP_IN].name
4458 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004459 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004460 filter->map[RMAP_IN].name, VTY_NEWLINE);
4461 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004462 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004463 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4464 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4465 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4466 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4467 if (filter->map[RMAP_EXPORT].name)
4468 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4469 || strcmp (filter->map[RMAP_EXPORT].name,
4470 gfilter->map[RMAP_EXPORT].name) != 0)
4471 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4472 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004473
4474 /* unsuppress-map */
4475 if (filter->usmap.name && ! gfilter)
4476 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4477 filter->usmap.name, VTY_NEWLINE);
4478
4479 /* filter-list. */
4480 if (filter->aslist[in].name)
4481 if (! gfilter || ! gfilter->aslist[in].name
4482 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4483 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4484 filter->aslist[in].name, VTY_NEWLINE);
4485 if (filter->aslist[out].name && ! gfilter)
4486 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4487 filter->aslist[out].name, VTY_NEWLINE);
4488}
4489
4490/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004491static void
paul718e3742002-12-13 20:15:29 +00004492bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4493 struct peer *peer, afi_t afi, safi_t safi)
4494{
4495 struct bgp_filter *filter;
4496 struct peer *g_peer = NULL;
4497 char buf[SU_ADDRSTRLEN];
4498 char *addr;
4499
4500 filter = &peer->filter[afi][safi];
4501 addr = peer->host;
4502 if (peer_group_active (peer))
4503 g_peer = peer->group->conf;
4504
4505 /************************************
4506 ****** Global to the neighbor ******
4507 ************************************/
4508 if (afi == AFI_IP && safi == SAFI_UNICAST)
4509 {
4510 /* remote-as. */
4511 if (! peer_group_active (peer))
4512 {
4513 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4514 vty_out (vty, " neighbor %s peer-group%s", addr,
4515 VTY_NEWLINE);
4516 if (peer->as)
4517 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4518 VTY_NEWLINE);
4519 }
4520 else
4521 {
4522 if (! g_peer->as)
4523 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4524 VTY_NEWLINE);
4525 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4526 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4527 peer->group->name, VTY_NEWLINE);
4528 }
4529
4530 /* local-as. */
4531 if (peer->change_local_as)
4532 if (! peer_group_active (peer))
4533 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4534 peer->change_local_as,
4535 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4536 " no-prepend" : "", VTY_NEWLINE);
4537
4538 /* Description. */
4539 if (peer->desc)
4540 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4541 VTY_NEWLINE);
4542
4543 /* Shutdown. */
4544 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4545 if (! peer_group_active (peer) ||
4546 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4547 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4548
Paul Jakma0df7c912008-07-21 21:02:49 +00004549 /* Password. */
4550 if (peer->password)
4551 if (!peer_group_active (peer)
4552 || ! g_peer->password
4553 || strcmp (peer->password, g_peer->password) != 0)
4554 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4555 VTY_NEWLINE);
4556
paul718e3742002-12-13 20:15:29 +00004557 /* BGP port. */
4558 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004559 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004560 VTY_NEWLINE);
4561
4562 /* Local interface name. */
4563 if (peer->ifname)
4564 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4565 VTY_NEWLINE);
4566
4567 /* Passive. */
4568 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4569 if (! peer_group_active (peer) ||
4570 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4571 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4572
4573 /* EBGP multihop. */
4574 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4575 if (! peer_group_active (peer) ||
4576 g_peer->ttl != peer->ttl)
4577 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4578 VTY_NEWLINE);
4579
hasso6ffd2072005-02-02 14:50:11 +00004580 /* disable-connected-check. */
4581 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004582 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004583 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4584 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004585
4586 /* Update-source. */
4587 if (peer->update_if)
4588 if (! peer_group_active (peer) || ! g_peer->update_if
4589 || strcmp (g_peer->update_if, peer->update_if) != 0)
4590 vty_out (vty, " neighbor %s update-source %s%s", addr,
4591 peer->update_if, VTY_NEWLINE);
4592 if (peer->update_source)
4593 if (! peer_group_active (peer) || ! g_peer->update_source
4594 || sockunion_cmp (g_peer->update_source,
4595 peer->update_source) != 0)
4596 vty_out (vty, " neighbor %s update-source %s%s", addr,
4597 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4598 VTY_NEWLINE);
4599
paul718e3742002-12-13 20:15:29 +00004600 /* advertisement-interval */
4601 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4602 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4603 addr, peer->v_routeadv, VTY_NEWLINE);
4604
4605 /* timers. */
4606 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4607 && ! peer_group_active (peer))
4608 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4609 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4610
4611 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4612 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4613 peer->connect, VTY_NEWLINE);
4614
4615 /* Default weight. */
4616 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4617 if (! peer_group_active (peer) ||
4618 g_peer->weight != peer->weight)
4619 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4620 VTY_NEWLINE);
4621
paul718e3742002-12-13 20:15:29 +00004622 /* Dynamic capability. */
4623 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4624 if (! peer_group_active (peer) ||
4625 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4626 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4627 VTY_NEWLINE);
4628
4629 /* dont capability negotiation. */
4630 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4631 if (! peer_group_active (peer) ||
4632 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4633 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4634 VTY_NEWLINE);
4635
4636 /* override capability negotiation. */
4637 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4638 if (! peer_group_active (peer) ||
4639 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4640 vty_out (vty, " neighbor %s override-capability%s", addr,
4641 VTY_NEWLINE);
4642
4643 /* strict capability negotiation. */
4644 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4645 if (! peer_group_active (peer) ||
4646 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4647 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4648 VTY_NEWLINE);
4649
4650 if (! peer_group_active (peer))
4651 {
4652 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4653 {
4654 if (peer->afc[AFI_IP][SAFI_UNICAST])
4655 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4656 }
4657 else
4658 {
4659 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4660 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4661 }
4662 }
4663 }
4664
4665
4666 /************************************
4667 ****** Per AF to the neighbor ******
4668 ************************************/
4669
4670 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4671 {
4672 if (peer->af_group[afi][safi])
4673 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4674 peer->group->name, VTY_NEWLINE);
4675 else
4676 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4677 }
4678
4679 /* ORF capability. */
4680 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4681 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4682 if (! peer->af_group[afi][safi])
4683 {
4684 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4685
4686 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4687 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4688 vty_out (vty, " both");
4689 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4690 vty_out (vty, " send");
4691 else
4692 vty_out (vty, " receive");
4693 vty_out (vty, "%s", VTY_NEWLINE);
4694 }
4695
4696 /* Route reflector client. */
4697 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4698 && ! peer->af_group[afi][safi])
4699 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4700 VTY_NEWLINE);
4701
4702 /* Nexthop self. */
4703 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4704 && ! peer->af_group[afi][safi])
4705 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4706
4707 /* Remove private AS. */
4708 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4709 && ! peer->af_group[afi][safi])
4710 vty_out (vty, " neighbor %s remove-private-AS%s",
4711 addr, VTY_NEWLINE);
4712
4713 /* send-community print. */
4714 if (! peer->af_group[afi][safi])
4715 {
4716 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4717 {
4718 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4719 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4720 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4721 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4722 vty_out (vty, " neighbor %s send-community extended%s",
4723 addr, VTY_NEWLINE);
4724 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4725 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4726 }
4727 else
4728 {
4729 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4730 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4731 vty_out (vty, " no neighbor %s send-community both%s",
4732 addr, VTY_NEWLINE);
4733 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4734 vty_out (vty, " no neighbor %s send-community extended%s",
4735 addr, VTY_NEWLINE);
4736 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4737 vty_out (vty, " no neighbor %s send-community%s",
4738 addr, VTY_NEWLINE);
4739 }
4740 }
4741
4742 /* Default information */
4743 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4744 && ! peer->af_group[afi][safi])
4745 {
4746 vty_out (vty, " neighbor %s default-originate", addr);
4747 if (peer->default_rmap[afi][safi].name)
4748 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4749 vty_out (vty, "%s", VTY_NEWLINE);
4750 }
4751
4752 /* Soft reconfiguration inbound. */
4753 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4754 if (! peer->af_group[afi][safi] ||
4755 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4756 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4757 VTY_NEWLINE);
4758
4759 /* maximum-prefix. */
4760 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4761 if (! peer->af_group[afi][safi]
4762 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004763 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004764 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4765 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004766 {
hasso0a486e52005-02-01 20:57:17 +00004767 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4768 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4769 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4770 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4771 vty_out (vty, " warning-only");
4772 if (peer->pmax_restart[afi][safi])
4773 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4774 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004775 }
paul718e3742002-12-13 20:15:29 +00004776
4777 /* Route server client. */
4778 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4779 && ! peer->af_group[afi][safi])
4780 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4781
4782 /* Allow AS in. */
4783 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4784 if (! peer_group_active (peer)
4785 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4786 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4787 {
4788 if (peer->allowas_in[afi][safi] == 3)
4789 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4790 else
4791 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4792 peer->allowas_in[afi][safi], VTY_NEWLINE);
4793 }
4794
4795 /* Filter. */
4796 bgp_config_write_filter (vty, peer, afi, safi);
4797
4798 /* atribute-unchanged. */
4799 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4800 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4801 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4802 && ! peer->af_group[afi][safi])
4803 {
4804 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4805 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4806 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4807 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4808 else
4809 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4810 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4811 " as-path" : "",
4812 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4813 " next-hop" : "",
4814 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4815 " med" : "", VTY_NEWLINE);
4816 }
4817}
4818
4819/* Display "address-family" configuration header. */
4820void
4821bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4822 int *write)
4823{
4824 if (*write)
4825 return;
4826
4827 if (afi == AFI_IP && safi == SAFI_UNICAST)
4828 return;
4829
4830 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4831
4832 if (afi == AFI_IP)
4833 {
4834 if (safi == SAFI_MULTICAST)
4835 vty_out (vty, "ipv4 multicast");
4836 else if (safi == SAFI_MPLS_VPN)
4837 vty_out (vty, "vpnv4 unicast");
4838 }
4839 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004840 {
4841 vty_out (vty, "ipv6");
4842
4843 if (safi == SAFI_MULTICAST)
4844 vty_out (vty, " multicast");
4845 }
paul718e3742002-12-13 20:15:29 +00004846
4847 vty_out (vty, "%s", VTY_NEWLINE);
4848
4849 *write = 1;
4850}
4851
4852/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004853static int
paul718e3742002-12-13 20:15:29 +00004854bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4855 safi_t safi)
4856{
4857 int write = 0;
4858 struct peer *peer;
4859 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004860 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004861
4862 bgp_config_write_network (vty, bgp, afi, safi, &write);
4863
4864 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4865
paul1eb8ef22005-04-07 07:30:20 +00004866 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004867 {
4868 if (group->conf->afc[afi][safi])
4869 {
4870 bgp_config_write_family_header (vty, afi, safi, &write);
4871 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4872 }
4873 }
paul1eb8ef22005-04-07 07:30:20 +00004874 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004875 {
4876 if (peer->afc[afi][safi])
4877 {
4878 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4879 {
4880 bgp_config_write_family_header (vty, afi, safi, &write);
4881 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4882 }
4883 }
4884 }
4885 if (write)
4886 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4887
4888 return write;
4889}
4890
4891int
4892bgp_config_write (struct vty *vty)
4893{
4894 int write = 0;
4895 struct bgp *bgp;
4896 struct peer_group *group;
4897 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004898 struct listnode *node, *nnode;
4899 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004900
4901 /* BGP Multiple instance. */
4902 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4903 {
4904 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4905 write++;
4906 }
4907
4908 /* BGP Config type. */
4909 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4910 {
4911 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4912 write++;
4913 }
4914
Paul Jakmad664ae12007-08-31 14:27:37 +01004915 /* BGP Open-Always */
4916 if (bgp_option_check (BGP_OPT_ALWAYS_OPEN))
4917 {
4918 vty_out (vty, "bgp open-accept%s", VTY_NEWLINE);
4919 write++;
4920 }
4921
paul718e3742002-12-13 20:15:29 +00004922 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004923 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004924 {
4925 if (write)
4926 vty_out (vty, "!%s", VTY_NEWLINE);
4927
4928 /* Router bgp ASN */
4929 vty_out (vty, "router bgp %d", bgp->as);
4930
4931 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4932 {
4933 if (bgp->name)
4934 vty_out (vty, " view %s", bgp->name);
4935 }
4936 vty_out (vty, "%s", VTY_NEWLINE);
4937
4938 /* No Synchronization */
4939 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4940 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4941
4942 /* BGP fast-external-failover. */
4943 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4944 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4945
4946 /* BGP router ID. */
4947 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4948 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4949 VTY_NEWLINE);
4950
paul848973c2003-08-13 00:32:49 +00004951 /* BGP log-neighbor-changes. */
4952 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4953 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4954
paul718e3742002-12-13 20:15:29 +00004955 /* BGP configuration. */
4956 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4957 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4958
4959 /* BGP default ipv4-unicast. */
4960 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4961 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4962
4963 /* BGP default local-preference. */
4964 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4965 vty_out (vty, " bgp default local-preference %d%s",
4966 bgp->default_local_pref, VTY_NEWLINE);
4967
4968 /* BGP client-to-client reflection. */
4969 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4970 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4971
4972 /* BGP cluster ID. */
4973 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4974 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4975 VTY_NEWLINE);
4976
hassoe0701b72004-05-20 09:19:34 +00004977 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004978 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004979 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4980 VTY_NEWLINE);
4981
4982 /* Confederation peer */
4983 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004984 {
hassoe0701b72004-05-20 09:19:34 +00004985 int i;
paul718e3742002-12-13 20:15:29 +00004986
hassoe0701b72004-05-20 09:19:34 +00004987 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004988
hassoe0701b72004-05-20 09:19:34 +00004989 for (i = 0; i < bgp->confed_peers_cnt; i++)
4990 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004991
hassoe0701b72004-05-20 09:19:34 +00004992 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004993 }
4994
4995 /* BGP enforce-first-as. */
4996 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4997 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4998
4999 /* BGP deterministic-med. */
5000 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5001 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005002
5003 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005004 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5005 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5006 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005007 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5008 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5009
paul718e3742002-12-13 20:15:29 +00005010 /* BGP bestpath method. */
5011 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5012 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005013 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5014 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005015 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5016 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5017 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5018 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5019 {
5020 vty_out (vty, " bgp bestpath med");
5021 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5022 vty_out (vty, " confed");
5023 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5024 vty_out (vty, " missing-as-worst");
5025 vty_out (vty, "%s", VTY_NEWLINE);
5026 }
5027
5028 /* BGP network import check. */
5029 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5030 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5031
5032 /* BGP scan interval. */
5033 bgp_config_write_scan_time (vty);
5034
5035 /* BGP flag dampening. */
5036 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5037 BGP_CONFIG_DAMPENING))
5038 bgp_config_write_damp (vty);
5039
5040 /* BGP static route configuration. */
5041 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5042
5043 /* BGP redistribute configuration. */
5044 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5045
5046 /* BGP timers configuration. */
5047 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5048 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5049 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5050 bgp->default_holdtime, VTY_NEWLINE);
5051
5052 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005053 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005054 {
5055 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5056 }
5057
5058 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005059 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005060 {
5061 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5062 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5063 }
5064
5065 /* Distance configuration. */
5066 bgp_config_write_distance (vty, bgp);
5067
5068 /* No auto-summary */
5069 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5070 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5071
5072 /* IPv4 multicast configuration. */
5073 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5074
5075 /* IPv4 VPN configuration. */
5076 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5077
5078 /* IPv6 unicast configuration. */
5079 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5080
Paul Jakma37a217a2007-04-10 19:20:29 +00005081 /* IPv6 multicast configuration. */
5082 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5083
paul718e3742002-12-13 20:15:29 +00005084 write++;
5085 }
5086 return write;
5087}
5088
5089void
paul94f2b392005-06-28 12:44:16 +00005090bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005091{
5092 memset (&bgp_master, 0, sizeof (struct bgp_master));
5093
5094 bm = &bgp_master;
5095 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005096 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005097 bm->port = BGP_PORT_DEFAULT;
5098 bm->master = thread_master_create ();
5099 bm->start_time = time (NULL);
5100}
paul200df112005-06-01 11:17:05 +00005101
paul718e3742002-12-13 20:15:29 +00005102
5103void
paul94f2b392005-06-28 12:44:16 +00005104bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005105{
paul718e3742002-12-13 20:15:29 +00005106 /* BGP VTY commands installation. */
5107 bgp_vty_init ();
5108
5109 /* Create BGP server socket. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +00005110 bgp_socket (NULL, bm->port, bm->address);
paul718e3742002-12-13 20:15:29 +00005111
5112 /* Init zebra. */
5113 bgp_zebra_init ();
5114
5115 /* BGP inits. */
5116 bgp_attr_init ();
5117 bgp_debug_init ();
5118 bgp_dump_init ();
5119 bgp_route_init ();
5120 bgp_route_map_init ();
5121 bgp_scan_init ();
5122 bgp_mplsvpn_init ();
5123
5124 /* Access list initialize. */
5125 access_list_init ();
5126 access_list_add_hook (peer_distribute_update);
5127 access_list_delete_hook (peer_distribute_update);
5128
5129 /* Filter list initialize. */
5130 bgp_filter_init ();
5131 as_list_add_hook (peer_aslist_update);
5132 as_list_delete_hook (peer_aslist_update);
5133
5134 /* Prefix list initialize.*/
5135 prefix_list_init ();
5136 prefix_list_add_hook (peer_prefix_list_update);
5137 prefix_list_delete_hook (peer_prefix_list_update);
5138
5139 /* Community list initialize. */
5140 bgp_clist = community_list_init ();
5141
5142#ifdef HAVE_SNMP
5143 bgp_snmp_init ();
5144#endif /* HAVE_SNMP */
5145}
paul545acaf2004-04-20 15:13:15 +00005146
5147void
5148bgp_terminate ()
5149{
paul545acaf2004-04-20 15:13:15 +00005150 struct bgp *bgp;
5151 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005152 struct listnode *node, *nnode;
5153 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005154
paul1eb8ef22005-04-07 07:30:20 +00005155 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5156 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005157 if (peer->status == Established)
5158 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5159 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005160
paul545acaf2004-04-20 15:13:15 +00005161 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00005162 if (bm->process_main_queue)
5163 work_queue_free (bm->process_main_queue);
5164 if (bm->process_rsclient_queue)
5165 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00005166}
5167