blob: ea365dec5c433788d1a0cc464b4529cc0fd4a12c [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:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
88 break;
89 }
90 return 0;
91}
92
93int
94bgp_option_unset (int flag)
95{
96 switch (flag)
97 {
98 case BGP_OPT_MULTIPLE_INSTANCE:
99 if (listcount (bm->bgp) > 1)
100 return BGP_ERR_MULTIPLE_INSTANCE_USED;
101 /* Fall through. */
102 case BGP_OPT_NO_FIB:
103 case BGP_OPT_CONFIG_CISCO:
104 UNSET_FLAG (bm->options, flag);
105 break;
106 default:
107 return BGP_ERR_INVALID_FLAG;
108 break;
109 }
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{
692 if (peer->desc)
693 XFREE (MTYPE_PEER_DESC, peer->desc);
694
695 /* Free allocated host character. */
696 if (peer->host)
697 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
698
699 /* Update source configuration. */
700 if (peer->update_source)
701 sockunion_free (peer->update_source);
702
703 if (peer->update_if)
704 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
705
706 memset (peer, 0, sizeof (struct peer));
707
708 XFREE (MTYPE_BGP_PEER, peer);
709}
710
711/* increase reference count on a struct peer */
712struct peer *
713peer_lock (struct peer *peer)
714{
715 assert (peer && (peer->lock >= 0));
716
717 peer->lock++;
718
719 return peer;
720}
721
722/* decrease reference count on a struct peer
723 * struct peer is freed and NULL returned if last reference
724 */
725struct peer *
726peer_unlock (struct peer *peer)
727{
728 assert (peer && (peer->lock > 0));
729
730 peer->lock--;
731
732 if (peer->lock == 0)
733 {
734#if 0
735 zlog_debug ("unlocked and freeing");
736 zlog_backtrace (LOG_DEBUG);
737#endif
738 peer_free (peer);
739 return NULL;
740 }
741
742#if 0
743 if (peer->lock == 1)
744 {
745 zlog_debug ("unlocked to 1");
746 zlog_backtrace (LOG_DEBUG);
747 }
748#endif
749
750 return peer;
751}
752
753/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000754static struct peer *
755peer_new ()
756{
757 afi_t afi;
758 safi_t safi;
759 struct peer *peer;
760 struct servent *sp;
761
762 /* Allocate new peer. */
763 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
764 memset (peer, 0, sizeof (struct peer));
765
766 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000767 peer->fd = -1;
paul200df112005-06-01 11:17:05 +0000768 peer->lock = 1;
paul718e3742002-12-13 20:15:29 +0000769 peer->v_start = BGP_INIT_START_TIMER;
770 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
771 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
772 peer->status = Idle;
773 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000774 peer->weight = 0;
775
776 /* Set default flags. */
777 for (afi = AFI_IP; afi < AFI_MAX; afi++)
778 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
779 {
780 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
781 {
782 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
783 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
784 }
785 peer->orf_plist[afi][safi] = NULL;
786 }
787 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
788
789 /* Create buffers. */
790 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
791 peer->obuf = stream_fifo_new ();
792 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
793
794 bgp_sync_init (peer);
795
796 /* Get service port number. */
797 sp = getservbyname ("bgp", "tcp");
798 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
799
800 return peer;
801}
802
803/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000804static struct peer *
paul718e3742002-12-13 20:15:29 +0000805peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
806 as_t remote_as, afi_t afi, safi_t safi)
807{
808 int active;
809 struct peer *peer;
810 char buf[SU_ADDRSTRLEN];
811
812 peer = peer_new ();
813 peer->bgp = bgp;
814 peer->su = *su;
815 peer->local_as = local_as;
816 peer->as = remote_as;
817 peer->local_id = bgp->router_id;
818 peer->v_holdtime = bgp->default_holdtime;
819 peer->v_keepalive = bgp->default_keepalive;
820 if (peer_sort (peer) == BGP_PEER_IBGP)
821 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
822 else
823 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000824
825 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000826 listnode_add_sort (bgp->peer, peer);
827
828 active = peer_active (peer);
829
830 if (afi && safi)
831 peer->afc[afi][safi] = 1;
832
833 /* Last read time set */
834 peer->readtime = time (NULL);
835
paul848973c2003-08-13 00:32:49 +0000836 /* Last reset time set */
837 peer->resettime = time (NULL);
838
paul718e3742002-12-13 20:15:29 +0000839 /* Default TTL set. */
840 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
841
842 /* Make peer's address string. */
843 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000844 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000845
846 /* Set up peer's events and timers. */
847 if (! active && peer_active (peer))
848 bgp_timer_set (peer);
849
850 return peer;
851}
852
pauleb821182004-05-01 08:44:08 +0000853/* Make accept BGP peer. Called from bgp_accept (). */
854struct peer *
855peer_create_accept (struct bgp *bgp)
856{
857 struct peer *peer;
858
859 peer = peer_new ();
860 peer->bgp = bgp;
paul200df112005-06-01 11:17:05 +0000861
862 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000863 listnode_add_sort (bgp->peer, peer);
864
865 return peer;
866}
867
paul718e3742002-12-13 20:15:29 +0000868/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000869static void
paul718e3742002-12-13 20:15:29 +0000870peer_as_change (struct peer *peer, as_t as)
871{
872 int type;
873
874 /* Stop peer. */
875 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
876 {
877 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000878 {
879 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
880 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
881 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
882 }
paul718e3742002-12-13 20:15:29 +0000883 else
884 BGP_EVENT_ADD (peer, BGP_Stop);
885 }
886 type = peer_sort (peer);
887 peer->as = as;
888
paul848973c2003-08-13 00:32:49 +0000889 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
890 && ! bgp_confederation_peers_check (peer->bgp, as)
891 && peer->bgp->as != as)
892 peer->local_as = peer->bgp->confed_id;
893 else
894 peer->local_as = peer->bgp->as;
895
paul718e3742002-12-13 20:15:29 +0000896 /* Advertisement-interval reset */
897 if (peer_sort (peer) == BGP_PEER_IBGP)
898 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
899 else
900 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
901
902 /* TTL reset */
903 if (peer_sort (peer) == BGP_PEER_IBGP)
904 peer->ttl = 255;
905 else if (type == BGP_PEER_IBGP)
906 peer->ttl = 1;
907
908 /* reflector-client reset */
909 if (peer_sort (peer) != BGP_PEER_IBGP)
910 {
911 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
912 PEER_FLAG_REFLECTOR_CLIENT);
913 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
914 PEER_FLAG_REFLECTOR_CLIENT);
915 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
916 PEER_FLAG_REFLECTOR_CLIENT);
917 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
918 PEER_FLAG_REFLECTOR_CLIENT);
919 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
920 PEER_FLAG_REFLECTOR_CLIENT);
921 }
922
923 /* local-as reset */
924 if (peer_sort (peer) != BGP_PEER_EBGP)
925 {
926 peer->change_local_as = 0;
927 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
928 }
929}
930
931/* If peer does not exist, create new one. If peer already exists,
932 set AS number to the peer. */
933int
934peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
935 afi_t afi, safi_t safi)
936{
937 struct peer *peer;
938 as_t local_as;
939
940 peer = peer_lookup (bgp, su);
941
942 if (peer)
943 {
944 /* When this peer is a member of peer-group. */
945 if (peer->group)
946 {
947 if (peer->group->conf->as)
948 {
949 /* Return peer group's AS number. */
950 *as = peer->group->conf->as;
951 return BGP_ERR_PEER_GROUP_MEMBER;
952 }
953 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
954 {
955 if (bgp->as != *as)
956 {
957 *as = peer->as;
958 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
959 }
960 }
961 else
962 {
963 if (bgp->as == *as)
964 {
965 *as = peer->as;
966 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
967 }
968 }
969 }
970
971 /* Existing peer's AS number change. */
972 if (peer->as != *as)
973 peer_as_change (peer, *as);
974 }
975 else
976 {
977
978 /* If the peer is not part of our confederation, and its not an
979 iBGP peer then spoof the source AS */
980 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
981 && ! bgp_confederation_peers_check (bgp, *as)
982 && bgp->as != *as)
983 local_as = bgp->confed_id;
984 else
985 local_as = bgp->as;
986
987 /* If this is IPv4 unicast configuration and "no bgp default
988 ipv4-unicast" is specified. */
989
990 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
991 && afi == AFI_IP && safi == SAFI_UNICAST)
992 peer = peer_create (su, bgp, local_as, *as, 0, 0);
993 else
994 peer = peer_create (su, bgp, local_as, *as, afi, safi);
995 }
996
997 return 0;
998}
999
1000/* Activate the peer or peer group for specified AFI and SAFI. */
1001int
1002peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1003{
1004 int active;
1005
1006 if (peer->afc[afi][safi])
1007 return 0;
1008
1009 /* Activate the address family configuration. */
1010 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1011 peer->afc[afi][safi] = 1;
1012 else
1013 {
1014 active = peer_active (peer);
1015
1016 peer->afc[afi][safi] = 1;
1017
1018 if (! active && peer_active (peer))
1019 bgp_timer_set (peer);
1020 else
1021 {
1022 if (peer->status == Established)
1023 {
1024 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1025 {
1026 peer->afc_adv[afi][safi] = 1;
1027 bgp_capability_send (peer, afi, safi,
1028 CAPABILITY_CODE_MP,
1029 CAPABILITY_ACTION_SET);
1030 if (peer->afc_recv[afi][safi])
1031 {
1032 peer->afc_nego[afi][safi] = 1;
1033 bgp_announce_route (peer, afi, safi);
1034 }
1035 }
1036 else
hassoe0701b72004-05-20 09:19:34 +00001037 {
1038 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1039 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1040 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1041 }
paul718e3742002-12-13 20:15:29 +00001042 }
1043 }
1044 }
1045 return 0;
1046}
1047
1048int
1049peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1050{
1051 struct peer_group *group;
1052 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001053 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001054
1055 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1056 {
1057 group = peer->group;
1058
paul1eb8ef22005-04-07 07:30:20 +00001059 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001060 {
1061 if (peer1->af_group[afi][safi])
1062 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1063 }
1064 }
1065 else
1066 {
1067 if (peer->af_group[afi][safi])
1068 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1069 }
1070
1071 if (! peer->afc[afi][safi])
1072 return 0;
1073
1074 /* De-activate the address family configuration. */
1075 peer->afc[afi][safi] = 0;
1076 peer_af_flag_reset (peer, afi, safi);
1077
1078 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1079 {
1080 if (peer->status == Established)
1081 {
1082 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1083 {
1084 peer->afc_adv[afi][safi] = 0;
1085 peer->afc_nego[afi][safi] = 0;
1086
1087 if (peer_active_nego (peer))
1088 {
1089 bgp_capability_send (peer, afi, safi,
1090 CAPABILITY_CODE_MP,
1091 CAPABILITY_ACTION_UNSET);
1092 bgp_clear_route (peer, afi, safi);
1093 peer->pcount[afi][safi] = 0;
1094 }
1095 else
hassoe0701b72004-05-20 09:19:34 +00001096 {
1097 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1098 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1099 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1100 }
paul718e3742002-12-13 20:15:29 +00001101 }
1102 else
hassoe0701b72004-05-20 09:19:34 +00001103 {
1104 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1105 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1106 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1107 }
paul718e3742002-12-13 20:15:29 +00001108 }
1109 }
1110 return 0;
1111}
1112
hasso93406d82005-02-02 14:40:33 +00001113void
1114peer_nsf_stop (struct peer *peer)
1115{
1116 afi_t afi;
1117 safi_t safi;
1118
1119 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1120 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1121
1122 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1123 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1124 peer->nsf[afi][safi] = 0;
1125
1126 if (peer->t_gr_restart)
1127 {
1128 BGP_TIMER_OFF (peer->t_gr_restart);
1129 if (BGP_DEBUG (events, EVENTS))
1130 zlog_debug ("%s graceful restart timer stopped", peer->host);
1131 }
1132 if (peer->t_gr_stale)
1133 {
1134 BGP_TIMER_OFF (peer->t_gr_stale);
1135 if (BGP_DEBUG (events, EVENTS))
1136 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1137 }
1138 bgp_clear_route_all (peer);
1139}
1140
paul718e3742002-12-13 20:15:29 +00001141/* Delete peer from confguration. */
1142int
1143peer_delete (struct peer *peer)
1144{
1145 int i;
1146 afi_t afi;
1147 safi_t safi;
1148 struct bgp *bgp;
1149 struct bgp_filter *filter;
1150
1151 bgp = peer->bgp;
1152
hasso93406d82005-02-02 14:40:33 +00001153 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1154 peer_nsf_stop (peer);
1155
paul718e3742002-12-13 20:15:29 +00001156 /* If this peer belongs to peer group. Clearn up the
1157 relationship. */
1158 if (peer->group)
1159 {
paul200df112005-06-01 11:17:05 +00001160 peer = peer_unlock (peer); /* peer-group reference */
paul718e3742002-12-13 20:15:29 +00001161 listnode_delete (peer->group->peer, peer);
1162 peer->group = NULL;
1163 }
paul200df112005-06-01 11:17:05 +00001164
paul718e3742002-12-13 20:15:29 +00001165 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001166 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1167 * executed after peer structure is deleted.
1168 */
hassoe0701b72004-05-20 09:19:34 +00001169 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001170 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001171 bgp_fsm_change_status (peer, Idle); /* stops all timers */
1172
1173 /* Stop all timers - should already have been done in bgp_stop */
paul718e3742002-12-13 20:15:29 +00001174 BGP_TIMER_OFF (peer->t_start);
1175 BGP_TIMER_OFF (peer->t_connect);
1176 BGP_TIMER_OFF (peer->t_holdtime);
1177 BGP_TIMER_OFF (peer->t_keepalive);
1178 BGP_TIMER_OFF (peer->t_asorig);
1179 BGP_TIMER_OFF (peer->t_routeadv);
hasso0a486e52005-02-01 20:57:17 +00001180 BGP_TIMER_OFF (peer->t_pmax_restart);
hasso93406d82005-02-02 14:40:33 +00001181 BGP_TIMER_OFF (peer->t_gr_restart);
1182 BGP_TIMER_OFF (peer->t_gr_stale);
paul718e3742002-12-13 20:15:29 +00001183
1184 /* Delete from all peer list. */
1185 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001186 {
paul200df112005-06-01 11:17:05 +00001187 peer_unlock (peer); /* bgp peer list reference */
1188 listnode_delete (bgp->peer, peer);
1189
paulfee0f4c2004-09-13 05:12:46 +00001190 if (peer_rsclient_active (peer))
paul200df112005-06-01 11:17:05 +00001191 {
1192 peer_unlock (peer); /* rsclient list reference */
1193 listnode_delete (bgp->rsclient, peer);
1194 }
paulfee0f4c2004-09-13 05:12:46 +00001195 }
1196
1197 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1198 member of a peer_group. */
1199 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1200 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1201 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1202 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001203
paul200df112005-06-01 11:17:05 +00001204 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001205 if (peer->ibuf)
1206 stream_free (peer->ibuf);
paul200df112005-06-01 11:17:05 +00001207
paul718e3742002-12-13 20:15:29 +00001208 if (peer->obuf)
1209 stream_fifo_free (peer->obuf);
1210
1211 if (peer->work)
1212 stream_free (peer->work);
paul200df112005-06-01 11:17:05 +00001213
paul718e3742002-12-13 20:15:29 +00001214 /* Local and remote addresses. */
1215 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001216 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001217 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001218 sockunion_free (peer->su_remote);
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 bgp_sync_delete (peer);
1221
1222 /* Free filter related memory. */
1223 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1224 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1225 {
1226 filter = &peer->filter[afi][safi];
1227
1228 for (i = FILTER_IN; i < FILTER_MAX; i++)
1229 {
1230 if (filter->dlist[i].name)
1231 free (filter->dlist[i].name);
1232 if (filter->plist[i].name)
1233 free (filter->plist[i].name);
1234 if (filter->aslist[i].name)
1235 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001236
1237 filter->dlist[i].name = NULL;
1238 filter->plist[i].name = NULL;
1239 filter->aslist[i].name = NULL;
1240 }
1241 for (i = RMAP_IN; i < RMAP_MAX; i++)
1242 {
paul718e3742002-12-13 20:15:29 +00001243 if (filter->map[i].name)
1244 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001245 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001246 }
1247
1248 if (filter->usmap.name)
1249 free (filter->usmap.name);
1250
1251 if (peer->default_rmap[afi][safi].name)
1252 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001253
1254 filter->usmap.name = NULL;
1255 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001256 }
paul200df112005-06-01 11:17:05 +00001257
1258 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001259
1260 return 0;
1261}
1262
paul94f2b392005-06-28 12:44:16 +00001263static int
paul718e3742002-12-13 20:15:29 +00001264peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1265{
1266 return strcmp (g1->name, g2->name);
1267}
1268
1269/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001270static int
paul718e3742002-12-13 20:15:29 +00001271peer_group_active (struct peer *peer)
1272{
1273 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1274 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1275 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1276 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1277 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1278 return 1;
1279 return 0;
1280}
1281
1282/* Peer group cofiguration. */
1283static struct peer_group *
1284peer_group_new ()
1285{
1286 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1287 sizeof (struct peer_group));
1288}
1289
paul94f2b392005-06-28 12:44:16 +00001290static void
paul718e3742002-12-13 20:15:29 +00001291peer_group_free (struct peer_group *group)
1292{
1293 XFREE (MTYPE_PEER_GROUP, group);
1294}
1295
1296struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001297peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001298{
1299 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001300 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001301
paul1eb8ef22005-04-07 07:30:20 +00001302 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001303 {
1304 if (strcmp (group->name, name) == 0)
1305 return group;
1306 }
1307 return NULL;
1308}
1309
1310struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001311peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001312{
1313 struct peer_group *group;
1314
1315 group = peer_group_lookup (bgp, name);
1316 if (group)
1317 return group;
1318
1319 group = peer_group_new ();
1320 group->bgp = bgp;
1321 group->name = strdup (name);
1322 group->peer = list_new ();
1323 group->conf = peer_new ();
1324 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1325 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1326 group->conf->host = strdup (name);
1327 group->conf->bgp = bgp;
1328 group->conf->group = group;
1329 group->conf->as = 0;
1330 group->conf->ttl = 1;
1331 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1332 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1333 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1334 group->conf->keepalive = 0;
1335 group->conf->holdtime = 0;
1336 group->conf->connect = 0;
1337 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1338 listnode_add_sort (bgp->group, group);
1339
1340 return 0;
1341}
1342
paul94f2b392005-06-28 12:44:16 +00001343static void
paul718e3742002-12-13 20:15:29 +00001344peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1345 afi_t afi, safi_t safi)
1346{
1347 int in = FILTER_IN;
1348 int out = FILTER_OUT;
1349 struct peer *conf;
1350 struct bgp_filter *pfilter;
1351 struct bgp_filter *gfilter;
1352
1353 conf = group->conf;
1354 pfilter = &peer->filter[afi][safi];
1355 gfilter = &conf->filter[afi][safi];
1356
1357 /* remote-as */
1358 if (conf->as)
1359 peer->as = conf->as;
1360
1361 /* remote-as */
1362 if (conf->change_local_as)
1363 peer->change_local_as = conf->change_local_as;
1364
1365 /* TTL */
1366 peer->ttl = conf->ttl;
1367
1368 /* Weight */
1369 peer->weight = conf->weight;
1370
1371 /* peer flags apply */
1372 peer->flags = conf->flags;
1373 /* peer af_flags apply */
1374 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1375 /* peer config apply */
1376 peer->config = conf->config;
1377
1378 /* peer timers apply */
1379 peer->holdtime = conf->holdtime;
1380 peer->keepalive = conf->keepalive;
1381 peer->connect = conf->connect;
1382 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1383 peer->v_connect = conf->connect;
1384 else
1385 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1386
1387 /* advertisement-interval reset */
1388 if (peer_sort (peer) == BGP_PEER_IBGP)
1389 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1390 else
1391 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1392
1393 /* maximum-prefix */
1394 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001395 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001396 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001397
1398 /* allowas-in */
1399 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1400
paulfee0f4c2004-09-13 05:12:46 +00001401 /* route-server-client */
1402 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1403 {
1404 /* Make peer's RIB point to group's RIB. */
1405 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1406
1407 /* Import policy. */
1408 if (pfilter->map[RMAP_IMPORT].name)
1409 free (pfilter->map[RMAP_IMPORT].name);
1410 if (gfilter->map[RMAP_IMPORT].name)
1411 {
1412 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1413 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1414 }
1415 else
1416 {
1417 pfilter->map[RMAP_IMPORT].name = NULL;
1418 pfilter->map[RMAP_IMPORT].map = NULL;
1419 }
1420
1421 /* Export policy. */
1422 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1423 {
1424 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1425 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1426 }
1427 }
1428
paul718e3742002-12-13 20:15:29 +00001429 /* default-originate route-map */
1430 if (conf->default_rmap[afi][safi].name)
1431 {
1432 if (peer->default_rmap[afi][safi].name)
1433 free (peer->default_rmap[afi][safi].name);
1434 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1435 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1436 }
1437
1438 /* update-source apply */
1439 if (conf->update_source)
1440 {
1441 if (peer->update_source)
1442 sockunion_free (peer->update_source);
1443 if (peer->update_if)
1444 {
1445 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1446 peer->update_if = NULL;
1447 }
1448 peer->update_source = sockunion_dup (conf->update_source);
1449 }
1450 else if (conf->update_if)
1451 {
1452 if (peer->update_if)
1453 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1454 if (peer->update_source)
1455 {
1456 sockunion_free (peer->update_source);
1457 peer->update_source = NULL;
1458 }
1459 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1460 }
1461
1462 /* inbound filter apply */
1463 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1464 {
1465 if (pfilter->dlist[in].name)
1466 free (pfilter->dlist[in].name);
1467 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1468 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1469 }
1470 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1471 {
1472 if (pfilter->plist[in].name)
1473 free (pfilter->plist[in].name);
1474 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1475 pfilter->plist[in].plist = gfilter->plist[in].plist;
1476 }
1477 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1478 {
1479 if (pfilter->aslist[in].name)
1480 free (pfilter->aslist[in].name);
1481 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1482 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1483 }
paulfee0f4c2004-09-13 05:12:46 +00001484 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001485 {
paulfee0f4c2004-09-13 05:12:46 +00001486 if (pfilter->map[RMAP_IN].name)
1487 free (pfilter->map[RMAP_IN].name);
1488 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1489 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001490 }
1491
1492 /* outbound filter apply */
1493 if (gfilter->dlist[out].name)
1494 {
1495 if (pfilter->dlist[out].name)
1496 free (pfilter->dlist[out].name);
1497 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1498 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1499 }
1500 else
1501 {
1502 if (pfilter->dlist[out].name)
1503 free (pfilter->dlist[out].name);
1504 pfilter->dlist[out].name = NULL;
1505 pfilter->dlist[out].alist = NULL;
1506 }
1507 if (gfilter->plist[out].name)
1508 {
1509 if (pfilter->plist[out].name)
1510 free (pfilter->plist[out].name);
1511 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1512 pfilter->plist[out].plist = gfilter->plist[out].plist;
1513 }
1514 else
1515 {
1516 if (pfilter->plist[out].name)
1517 free (pfilter->plist[out].name);
1518 pfilter->plist[out].name = NULL;
1519 pfilter->plist[out].plist = NULL;
1520 }
1521 if (gfilter->aslist[out].name)
1522 {
1523 if (pfilter->aslist[out].name)
1524 free (pfilter->aslist[out].name);
1525 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1526 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1527 }
1528 else
1529 {
1530 if (pfilter->aslist[out].name)
1531 free (pfilter->aslist[out].name);
1532 pfilter->aslist[out].name = NULL;
1533 pfilter->aslist[out].aslist = NULL;
1534 }
paulfee0f4c2004-09-13 05:12:46 +00001535 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001536 {
paulfee0f4c2004-09-13 05:12:46 +00001537 if (pfilter->map[RMAP_OUT].name)
1538 free (pfilter->map[RMAP_OUT].name);
1539 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1540 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001541 }
1542 else
1543 {
paulfee0f4c2004-09-13 05:12:46 +00001544 if (pfilter->map[RMAP_OUT].name)
1545 free (pfilter->map[RMAP_OUT].name);
1546 pfilter->map[RMAP_OUT].name = NULL;
1547 pfilter->map[RMAP_OUT].map = NULL;
1548 }
1549
1550 /* RS-client's import/export route-maps. */
1551 if (gfilter->map[RMAP_IMPORT].name)
1552 {
1553 if (pfilter->map[RMAP_IMPORT].name)
1554 free (pfilter->map[RMAP_IMPORT].name);
1555 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1556 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1557 }
1558 else
1559 {
1560 if (pfilter->map[RMAP_IMPORT].name)
1561 free (pfilter->map[RMAP_IMPORT].name);
1562 pfilter->map[RMAP_IMPORT].name = NULL;
1563 pfilter->map[RMAP_IMPORT].map = NULL;
1564 }
1565 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1566 {
1567 if (pfilter->map[RMAP_EXPORT].name)
1568 free (pfilter->map[RMAP_EXPORT].name);
1569 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1570 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001571 }
1572
1573 if (gfilter->usmap.name)
1574 {
1575 if (pfilter->usmap.name)
1576 free (pfilter->usmap.name);
1577 pfilter->usmap.name = strdup (gfilter->usmap.name);
1578 pfilter->usmap.map = gfilter->usmap.map;
1579 }
1580 else
1581 {
1582 if (pfilter->usmap.name)
1583 free (pfilter->usmap.name);
1584 pfilter->usmap.name = NULL;
1585 pfilter->usmap.map = NULL;
1586 }
1587}
1588
1589/* Peer group's remote AS configuration. */
1590int
paulfd79ac92004-10-13 05:06:08 +00001591peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001592{
1593 struct peer_group *group;
1594 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001595 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001596
1597 group = peer_group_lookup (bgp, group_name);
1598 if (! group)
1599 return -1;
1600
1601 if (group->conf->as == *as)
1602 return 0;
1603
1604 /* When we setup peer-group AS number all peer group member's AS
1605 number must be updated to same number. */
1606 peer_as_change (group->conf, *as);
1607
paul1eb8ef22005-04-07 07:30:20 +00001608 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001609 {
1610 if (peer->as != *as)
1611 peer_as_change (peer, *as);
1612 }
1613
1614 return 0;
1615}
1616
1617int
1618peer_group_delete (struct peer_group *group)
1619{
1620 struct bgp *bgp;
1621 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001622 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001623
1624 bgp = group->bgp;
1625
paul1eb8ef22005-04-07 07:30:20 +00001626 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001627 {
1628 peer->group = NULL;
1629 peer_delete (peer);
1630 }
1631 list_delete (group->peer);
1632
1633 free (group->name);
1634 group->name = NULL;
1635
1636 group->conf->group = NULL;
1637 peer_delete (group->conf);
1638
1639 /* Delete from all peer_group list. */
1640 listnode_delete (bgp->group, group);
1641
1642 peer_group_free (group);
1643
1644 return 0;
1645}
1646
1647int
1648peer_group_remote_as_delete (struct peer_group *group)
1649{
1650 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001651 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001652
1653 if (! group->conf->as)
1654 return 0;
1655
paul1eb8ef22005-04-07 07:30:20 +00001656 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001657 {
1658 peer->group = NULL;
1659 peer_delete (peer);
1660 }
1661 list_delete_all_node (group->peer);
1662
1663 group->conf->as = 0;
1664
1665 return 0;
1666}
1667
1668/* Bind specified peer to peer group. */
1669int
1670peer_group_bind (struct bgp *bgp, union sockunion *su,
1671 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1672{
1673 struct peer *peer;
1674 int first_member = 0;
1675
1676 /* Check peer group's address family. */
1677 if (! group->conf->afc[afi][safi])
1678 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1679
1680 /* Lookup the peer. */
1681 peer = peer_lookup (bgp, su);
1682
1683 /* Create a new peer. */
1684 if (! peer)
1685 {
1686 if (! group->conf->as)
1687 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1688
1689 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1690 peer->group = group;
1691 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001692
1693 peer = peer_lock (peer); /* peer-group group->peer reference */
paul718e3742002-12-13 20:15:29 +00001694 listnode_add (group->peer, peer);
1695 peer_group2peer_config_copy (group, peer, afi, safi);
1696
1697 return 0;
1698 }
1699
1700 /* When the peer already belongs to peer group, check the consistency. */
1701 if (peer->af_group[afi][safi])
1702 {
1703 if (strcmp (peer->group->name, group->name) != 0)
1704 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1705
1706 return 0;
1707 }
1708
1709 /* Check current peer group configuration. */
1710 if (peer_group_active (peer)
1711 && strcmp (peer->group->name, group->name) != 0)
1712 return BGP_ERR_PEER_GROUP_MISMATCH;
1713
1714 if (! group->conf->as)
1715 {
1716 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1717 && peer_sort (group->conf) != peer_sort (peer))
1718 {
1719 if (as)
1720 *as = peer->as;
1721 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1722 }
1723
1724 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1725 first_member = 1;
1726 }
1727
1728 peer->af_group[afi][safi] = 1;
1729 peer->afc[afi][safi] = 1;
1730 if (! peer->group)
1731 {
1732 peer->group = group;
paul200df112005-06-01 11:17:05 +00001733
1734 peer = peer_lock (peer); /* peer-group group->peer reference */
paul718e3742002-12-13 20:15:29 +00001735 listnode_add (group->peer, peer);
1736 }
1737
1738 if (first_member)
1739 {
1740 /* Advertisement-interval reset */
1741 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1742 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1743 else
1744 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1745
1746 /* ebgp-multihop reset */
1747 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1748 group->conf->ttl = 255;
1749
1750 /* local-as reset */
1751 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1752 {
1753 group->conf->change_local_as = 0;
1754 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1755 }
1756 }
paulfee0f4c2004-09-13 05:12:46 +00001757
1758 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1759 {
1760 /* If it's not configured as RSERVER_CLIENT in any other address
1761 family, without being member of a peer_group, remove it from
1762 list bgp->rsclient.*/
1763 if (! peer_rsclient_active (peer))
paul200df112005-06-01 11:17:05 +00001764 {
1765 peer_unlock (peer); /* peer rsclient reference */
1766 listnode_delete (bgp->rsclient, peer);
1767 }
paulfee0f4c2004-09-13 05:12:46 +00001768
1769 bgp_table_finish (peer->rib[afi][safi]);
1770
1771 /* Import policy. */
1772 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1773 {
1774 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1775 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1776 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1777 }
1778
1779 /* Export policy. */
1780 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1781 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1782 {
1783 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1784 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1785 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1786 }
1787 }
1788
paul718e3742002-12-13 20:15:29 +00001789 peer_group2peer_config_copy (group, peer, afi, safi);
1790
1791 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001792 {
1793 peer->last_reset = PEER_DOWN_RMAP_BIND;
1794 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1795 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1796 }
paul718e3742002-12-13 20:15:29 +00001797 else
1798 BGP_EVENT_ADD (peer, BGP_Stop);
1799
1800 return 0;
1801}
1802
1803int
1804peer_group_unbind (struct bgp *bgp, struct peer *peer,
1805 struct peer_group *group, afi_t afi, safi_t safi)
1806{
1807 if (! peer->af_group[afi][safi])
1808 return 0;
1809
1810 if (group != peer->group)
1811 return BGP_ERR_PEER_GROUP_MISMATCH;
1812
1813 peer->af_group[afi][safi] = 0;
1814 peer->afc[afi][safi] = 0;
1815 peer_af_flag_reset (peer, afi, safi);
1816
paulfee0f4c2004-09-13 05:12:46 +00001817 if (peer->rib[afi][safi])
1818 peer->rib[afi][safi] = NULL;
1819
paul718e3742002-12-13 20:15:29 +00001820 if (! peer_group_active (peer))
1821 {
paul200df112005-06-01 11:17:05 +00001822 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001823 listnode_delete (group->peer, peer);
1824 peer->group = NULL;
1825 if (group->conf->as)
1826 {
1827 peer_delete (peer);
1828 return 0;
1829 }
1830 peer_global_config_reset (peer);
1831 }
1832
1833 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001834 {
1835 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1836 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1837 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1838 }
paul718e3742002-12-13 20:15:29 +00001839 else
1840 BGP_EVENT_ADD (peer, BGP_Stop);
1841
1842 return 0;
1843}
1844
1845/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001846static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001847bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001848{
1849 struct bgp *bgp;
1850 afi_t afi;
1851 safi_t safi;
1852
paul200df112005-06-01 11:17:05 +00001853 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1854 return NULL;
1855
paul718e3742002-12-13 20:15:29 +00001856 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001857 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001858
1859 bgp->peer = list_new ();
1860 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1861
1862 bgp->group = list_new ();
1863 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1864
paulfee0f4c2004-09-13 05:12:46 +00001865 bgp->rsclient = list_new ();
1866 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1867
paul718e3742002-12-13 20:15:29 +00001868 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1869 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1870 {
1871 bgp->route[afi][safi] = bgp_table_init ();
1872 bgp->aggregate[afi][safi] = bgp_table_init ();
1873 bgp->rib[afi][safi] = bgp_table_init ();
1874 }
1875
1876 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1877 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1878 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001879 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1880 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001881
1882 bgp->as = *as;
1883
1884 if (name)
1885 bgp->name = strdup (name);
1886
1887 return bgp;
1888}
1889
1890/* Return first entry of BGP. */
1891struct bgp *
paul94f2b392005-06-28 12:44:16 +00001892bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001893{
1894 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001895 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001896 return NULL;
1897}
1898
1899/* Lookup BGP entry. */
1900struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001901bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001902{
1903 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001904 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001905
paul1eb8ef22005-04-07 07:30:20 +00001906 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001907 if (bgp->as == as
1908 && ((bgp->name == NULL && name == NULL)
1909 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1910 return bgp;
1911 return NULL;
1912}
1913
1914/* Lookup BGP structure by view name. */
1915struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001916bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001917{
1918 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001919 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001920
paul1eb8ef22005-04-07 07:30:20 +00001921 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001922 if ((bgp->name == NULL && name == NULL)
1923 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1924 return bgp;
1925 return NULL;
1926}
1927
1928/* Called from VTY commands. */
1929int
paulfd79ac92004-10-13 05:06:08 +00001930bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001931{
1932 struct bgp *bgp;
1933
1934 /* Multiple instance check. */
1935 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1936 {
1937 if (name)
1938 bgp = bgp_lookup_by_name (name);
1939 else
1940 bgp = bgp_get_default ();
1941
1942 /* Already exists. */
1943 if (bgp)
1944 {
1945 if (bgp->as != *as)
1946 {
1947 *as = bgp->as;
1948 return BGP_ERR_INSTANCE_MISMATCH;
1949 }
1950 *bgp_val = bgp;
1951 return 0;
1952 }
1953 }
1954 else
1955 {
1956 /* BGP instance name can not be specified for single instance. */
1957 if (name)
1958 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1959
1960 /* Get default BGP structure if exists. */
1961 bgp = bgp_get_default ();
1962
1963 if (bgp)
1964 {
1965 if (bgp->as != *as)
1966 {
1967 *as = bgp->as;
1968 return BGP_ERR_AS_MISMATCH;
1969 }
1970 *bgp_val = bgp;
1971 return 0;
1972 }
1973 }
1974
1975 bgp = bgp_create (as, name);
1976 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001977 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001978 *bgp_val = bgp;
1979
1980 return 0;
1981}
1982
1983/* Delete BGP instance. */
1984int
1985bgp_delete (struct bgp *bgp)
1986{
1987 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00001988 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001989 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001990 struct listnode *next;
1991 afi_t afi;
1992 safi_t safi;
1993 int i;
1994
1995 /* Delete static route. */
1996 bgp_static_delete (bgp);
1997
1998 /* Unset redistribution. */
1999 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2000 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2001 if (i != ZEBRA_ROUTE_BGP)
2002 bgp_redistribute_unset (bgp, afi, i);
2003
hassob6b7cff2005-05-26 08:29:07 +00002004 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2005 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002006 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002007
paul1eb8ef22005-04-07 07:30:20 +00002008 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2009 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002010 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002011
hasso54a6ed32005-05-26 22:12:33 +00002012 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2013 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002014 list_delete (bgp->rsclient);
2015
paul718e3742002-12-13 20:15:29 +00002016 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002017
paul718e3742002-12-13 20:15:29 +00002018 if (bgp->name)
2019 free (bgp->name);
2020
2021 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2022 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2023 {
2024 if (bgp->route[afi][safi])
2025 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2026 if (bgp->aggregate[afi][safi])
2027 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2028 if (bgp->rib[afi][safi])
2029 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2030 }
2031 XFREE (MTYPE_BGP, bgp);
2032
2033 return 0;
2034}
2035
2036struct peer *
2037peer_lookup (struct bgp *bgp, union sockunion *su)
2038{
2039 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002040 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002041
2042 if (! bgp)
2043 bgp = bgp_get_default ();
2044
2045 if (! bgp)
2046 return NULL;
2047
paul1eb8ef22005-04-07 07:30:20 +00002048 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002049 {
pauleb821182004-05-01 08:44:08 +00002050 if (sockunion_same (&peer->su, su)
2051 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2052 return peer;
paul718e3742002-12-13 20:15:29 +00002053 }
2054 return NULL;
2055}
2056
2057struct peer *
2058peer_lookup_with_open (union sockunion *su, as_t remote_as,
2059 struct in_addr *remote_id, int *as)
2060{
2061 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002062 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002063 struct bgp *bgp;
2064
2065 bgp = bgp_get_default ();
2066 if (! bgp)
2067 return NULL;
2068
paul1eb8ef22005-04-07 07:30:20 +00002069 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002070 {
pauleb821182004-05-01 08:44:08 +00002071 if (sockunion_same (&peer->su, su)
2072 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2073 {
2074 if (peer->as == remote_as
2075 && peer->remote_id.s_addr == remote_id->s_addr)
2076 return peer;
2077 if (peer->as == remote_as)
2078 *as = 1;
2079 }
paul718e3742002-12-13 20:15:29 +00002080 }
paul1eb8ef22005-04-07 07:30:20 +00002081 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002082 {
pauleb821182004-05-01 08:44:08 +00002083 if (sockunion_same (&peer->su, su)
2084 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2085 {
2086 if (peer->as == remote_as
2087 && peer->remote_id.s_addr == 0)
2088 return peer;
2089 if (peer->as == remote_as)
2090 *as = 1;
2091 }
paul718e3742002-12-13 20:15:29 +00002092 }
2093 return NULL;
2094}
2095
2096/* If peer is configured at least one address family return 1. */
2097int
2098peer_active (struct peer *peer)
2099{
2100 if (peer->afc[AFI_IP][SAFI_UNICAST]
2101 || peer->afc[AFI_IP][SAFI_MULTICAST]
2102 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2103 || peer->afc[AFI_IP6][SAFI_UNICAST]
2104 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2105 return 1;
2106 return 0;
2107}
2108
2109/* If peer is negotiated at least one address family return 1. */
2110int
2111peer_active_nego (struct peer *peer)
2112{
2113 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2114 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2115 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2116 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2117 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2118 return 1;
2119 return 0;
2120}
2121
2122/* peer_flag_change_type. */
2123enum peer_change_type
2124{
2125 peer_change_none,
2126 peer_change_reset,
2127 peer_change_reset_in,
2128 peer_change_reset_out,
2129};
2130
paul94f2b392005-06-28 12:44:16 +00002131static void
paul718e3742002-12-13 20:15:29 +00002132peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2133 enum peer_change_type type)
2134{
2135 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2136 return;
2137
2138 if (type == peer_change_reset)
2139 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2140 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2141 else if (type == peer_change_reset_in)
2142 {
2143 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2144 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2145 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2146 else
2147 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2148 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2149 }
2150 else if (type == peer_change_reset_out)
2151 bgp_announce_route (peer, afi, safi);
2152}
2153
2154struct peer_flag_action
2155{
2156 /* Peer's flag. */
2157 u_int32_t flag;
2158
2159 /* This flag can be set for peer-group member. */
2160 u_char not_for_member;
2161
2162 /* Action when the flag is changed. */
2163 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002164
2165 /* Peer down cause */
2166 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002167};
2168
2169struct peer_flag_action peer_flag_action_list[] =
2170 {
2171 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2172 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2173 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2174 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2175 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002176 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002177 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002178 { 0, 0, 0 }
2179 };
2180
2181struct peer_flag_action peer_af_flag_action_list[] =
2182 {
2183 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2184 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2185 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2186 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2187 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2188 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2189 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2190 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2191 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2192 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2193 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2194 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2195 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002196 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002197 { 0, 0, 0 }
2198 };
2199
2200/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002201static int
paul718e3742002-12-13 20:15:29 +00002202peer_flag_action_set (struct peer_flag_action *action_list, int size,
2203 struct peer_flag_action *action, u_int32_t flag)
2204{
2205 int i;
2206 int found = 0;
2207 int reset_in = 0;
2208 int reset_out = 0;
2209 struct peer_flag_action *match = NULL;
2210
2211 /* Check peer's frag action. */
2212 for (i = 0; i < size; i++)
2213 {
2214 match = &action_list[i];
2215
2216 if (match->flag == 0)
2217 break;
2218
2219 if (match->flag & flag)
2220 {
2221 found = 1;
2222
2223 if (match->type == peer_change_reset_in)
2224 reset_in = 1;
2225 if (match->type == peer_change_reset_out)
2226 reset_out = 1;
2227 if (match->type == peer_change_reset)
2228 {
2229 reset_in = 1;
2230 reset_out = 1;
2231 }
2232 if (match->not_for_member)
2233 action->not_for_member = 1;
2234 }
2235 }
2236
2237 /* Set peer clear type. */
2238 if (reset_in && reset_out)
2239 action->type = peer_change_reset;
2240 else if (reset_in)
2241 action->type = peer_change_reset_in;
2242 else if (reset_out)
2243 action->type = peer_change_reset_out;
2244 else
2245 action->type = peer_change_none;
2246
2247 return found;
2248}
2249
paul94f2b392005-06-28 12:44:16 +00002250static void
paul718e3742002-12-13 20:15:29 +00002251peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2252{
2253 if (flag == PEER_FLAG_SHUTDOWN)
2254 {
2255 if (CHECK_FLAG (peer->flags, flag))
2256 {
hasso93406d82005-02-02 14:40:33 +00002257 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2258 peer_nsf_stop (peer);
2259
hasso0a486e52005-02-01 20:57:17 +00002260 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2261 if (peer->t_pmax_restart)
2262 {
2263 BGP_TIMER_OFF (peer->t_pmax_restart);
2264 if (BGP_DEBUG (events, EVENTS))
2265 zlog_debug ("%s Maximum-prefix restart timer canceled",
2266 peer->host);
2267 }
2268
hasso93406d82005-02-02 14:40:33 +00002269 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2270 peer_nsf_stop (peer);
2271
paul718e3742002-12-13 20:15:29 +00002272 if (peer->status == Established)
2273 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2274 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2275 else
2276 BGP_EVENT_ADD (peer, BGP_Stop);
2277 }
2278 else
2279 {
2280 peer->v_start = BGP_INIT_START_TIMER;
2281 BGP_EVENT_ADD (peer, BGP_Stop);
2282 }
2283 }
2284 else if (peer->status == Established)
2285 {
hassoc9502432005-02-01 22:01:48 +00002286 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2287 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2288 else if (flag == PEER_FLAG_PASSIVE)
2289 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002290 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002291 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002292
hassoc9502432005-02-01 22:01:48 +00002293 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2294 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002295 }
2296 else
2297 BGP_EVENT_ADD (peer, BGP_Stop);
2298}
2299
2300/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002301static int
paul718e3742002-12-13 20:15:29 +00002302peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2303{
2304 int found;
2305 int size;
2306 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002307 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002308 struct peer_flag_action action;
2309
2310 memset (&action, 0, sizeof (struct peer_flag_action));
2311 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2312
2313 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2314
2315 /* No flag action is found. */
2316 if (! found)
2317 return BGP_ERR_INVALID_FLAG;
2318
2319 /* Not for peer-group member. */
2320 if (action.not_for_member && peer_group_active (peer))
2321 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2322
2323 /* When unset the peer-group member's flag we have to check
2324 peer-group configuration. */
2325 if (! set && peer_group_active (peer))
2326 if (CHECK_FLAG (peer->group->conf->flags, flag))
2327 {
2328 if (flag == PEER_FLAG_SHUTDOWN)
2329 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2330 else
2331 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2332 }
2333
2334 /* Flag conflict check. */
2335 if (set
2336 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2337 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2338 return BGP_ERR_PEER_FLAG_CONFLICT;
2339
2340 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2341 {
2342 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2343 return 0;
2344 if (! set && ! CHECK_FLAG (peer->flags, flag))
2345 return 0;
2346 }
2347
2348 if (set)
2349 SET_FLAG (peer->flags, flag);
2350 else
2351 UNSET_FLAG (peer->flags, flag);
2352
2353 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2354 {
2355 if (action.type == peer_change_reset)
2356 peer_flag_modify_action (peer, flag);
2357
2358 return 0;
2359 }
2360
2361 /* peer-group member updates. */
2362 group = peer->group;
2363
paul1eb8ef22005-04-07 07:30:20 +00002364 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002365 {
2366 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2367 continue;
2368
2369 if (! set && ! CHECK_FLAG (peer->flags, flag))
2370 continue;
2371
2372 if (set)
2373 SET_FLAG (peer->flags, flag);
2374 else
2375 UNSET_FLAG (peer->flags, flag);
2376
2377 if (action.type == peer_change_reset)
2378 peer_flag_modify_action (peer, flag);
2379 }
2380 return 0;
2381}
2382
2383int
2384peer_flag_set (struct peer *peer, u_int32_t flag)
2385{
2386 return peer_flag_modify (peer, flag, 1);
2387}
2388
2389int
2390peer_flag_unset (struct peer *peer, u_int32_t flag)
2391{
2392 return peer_flag_modify (peer, flag, 0);
2393}
2394
paul94f2b392005-06-28 12:44:16 +00002395static int
paul718e3742002-12-13 20:15:29 +00002396peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2397{
2398 if (peer->af_group[afi][safi])
2399 return 1;
2400 return 0;
2401}
2402
paul94f2b392005-06-28 12:44:16 +00002403static int
paul718e3742002-12-13 20:15:29 +00002404peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2405 int set)
2406{
2407 int found;
2408 int size;
paul1eb8ef22005-04-07 07:30:20 +00002409 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002410 struct peer_group *group;
2411 struct peer_flag_action action;
2412
2413 memset (&action, 0, sizeof (struct peer_flag_action));
2414 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2415
2416 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2417
2418 /* No flag action is found. */
2419 if (! found)
2420 return BGP_ERR_INVALID_FLAG;
2421
2422 /* Adress family must be activated. */
2423 if (! peer->afc[afi][safi])
2424 return BGP_ERR_PEER_INACTIVE;
2425
2426 /* Not for peer-group member. */
2427 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2428 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2429
2430 /* Spcecial check for reflector client. */
2431 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2432 && peer_sort (peer) != BGP_PEER_IBGP)
2433 return BGP_ERR_NOT_INTERNAL_PEER;
2434
2435 /* Spcecial check for remove-private-AS. */
2436 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2437 && peer_sort (peer) == BGP_PEER_IBGP)
2438 return BGP_ERR_REMOVE_PRIVATE_AS;
2439
2440 /* When unset the peer-group member's flag we have to check
2441 peer-group configuration. */
2442 if (! set && peer->af_group[afi][safi])
2443 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2444 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2445
2446 /* When current flag configuration is same as requested one. */
2447 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2448 {
2449 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2450 return 0;
2451 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2452 return 0;
2453 }
2454
2455 if (set)
2456 SET_FLAG (peer->af_flags[afi][safi], flag);
2457 else
2458 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2459
2460 /* Execute action when peer is established. */
2461 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2462 && peer->status == Established)
2463 {
2464 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2465 bgp_clear_adj_in (peer, afi, safi);
2466 else
hassoe0701b72004-05-20 09:19:34 +00002467 {
2468 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2469 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2470 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2471 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2472 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2473 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2474 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2475 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2476
2477 peer_change_action (peer, afi, safi, action.type);
2478 }
2479
paul718e3742002-12-13 20:15:29 +00002480 }
2481
2482 /* Peer group member updates. */
2483 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2484 {
2485 group = peer->group;
2486
paul1eb8ef22005-04-07 07:30:20 +00002487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002488 {
2489 if (! peer->af_group[afi][safi])
2490 continue;
2491
2492 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2493 continue;
2494
2495 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2496 continue;
2497
2498 if (set)
2499 SET_FLAG (peer->af_flags[afi][safi], flag);
2500 else
2501 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2502
2503 if (peer->status == Established)
2504 {
2505 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2506 bgp_clear_adj_in (peer, afi, safi);
2507 else
hassoe0701b72004-05-20 09:19:34 +00002508 {
2509 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2510 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2511 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2512 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2513 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2514 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2515 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2516 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2517
2518 peer_change_action (peer, afi, safi, action.type);
2519 }
paul718e3742002-12-13 20:15:29 +00002520 }
2521 }
2522 }
2523 return 0;
2524}
2525
2526int
2527peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2528{
2529 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2530}
2531
2532int
2533peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2534{
2535 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2536}
2537
2538/* EBGP multihop configuration. */
2539int
2540peer_ebgp_multihop_set (struct peer *peer, int ttl)
2541{
2542 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002543 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002544
2545 if (peer_sort (peer) == BGP_PEER_IBGP)
2546 return 0;
2547
2548 peer->ttl = ttl;
2549
2550 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2551 {
pauleb821182004-05-01 08:44:08 +00002552 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2553 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002554 }
2555 else
2556 {
2557 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002558 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002559 {
2560 if (peer_sort (peer) == BGP_PEER_IBGP)
2561 continue;
paul718e3742002-12-13 20:15:29 +00002562
pauleb821182004-05-01 08:44:08 +00002563 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002564
pauleb821182004-05-01 08:44:08 +00002565 if (peer->fd >= 0)
2566 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2567 }
paul718e3742002-12-13 20:15:29 +00002568 }
2569 return 0;
2570}
2571
2572int
2573peer_ebgp_multihop_unset (struct peer *peer)
2574{
2575 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002576 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002577
2578 if (peer_sort (peer) == BGP_PEER_IBGP)
2579 return 0;
2580
2581 if (peer_group_active (peer))
2582 peer->ttl = peer->group->conf->ttl;
2583 else
2584 peer->ttl = 1;
2585
2586 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2587 {
pauleb821182004-05-01 08:44:08 +00002588 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2589 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002590 }
2591 else
2592 {
2593 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002594 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002595 {
2596 if (peer_sort (peer) == BGP_PEER_IBGP)
2597 continue;
paul718e3742002-12-13 20:15:29 +00002598
pauleb821182004-05-01 08:44:08 +00002599 peer->ttl = 1;
2600
2601 if (peer->fd >= 0)
2602 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2603 }
paul718e3742002-12-13 20:15:29 +00002604 }
2605 return 0;
2606}
2607
2608/* Neighbor description. */
2609int
2610peer_description_set (struct peer *peer, char *desc)
2611{
2612 if (peer->desc)
2613 XFREE (MTYPE_PEER_DESC, peer->desc);
2614
2615 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2616
2617 return 0;
2618}
2619
2620int
2621peer_description_unset (struct peer *peer)
2622{
2623 if (peer->desc)
2624 XFREE (MTYPE_PEER_DESC, peer->desc);
2625
2626 peer->desc = NULL;
2627
2628 return 0;
2629}
2630
2631/* Neighbor update-source. */
2632int
paulfd79ac92004-10-13 05:06:08 +00002633peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002634{
2635 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002636 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002637
2638 if (peer->update_if)
2639 {
2640 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2641 && strcmp (peer->update_if, ifname) == 0)
2642 return 0;
2643
2644 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2645 peer->update_if = NULL;
2646 }
2647
2648 if (peer->update_source)
2649 {
2650 sockunion_free (peer->update_source);
2651 peer->update_source = NULL;
2652 }
2653
2654 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2655
2656 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2657 {
2658 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002659 {
2660 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2661 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2662 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2663 }
paul718e3742002-12-13 20:15:29 +00002664 else
2665 BGP_EVENT_ADD (peer, BGP_Stop);
2666 return 0;
2667 }
2668
2669 /* peer-group member updates. */
2670 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002671 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002672 {
2673 if (peer->update_if)
2674 {
2675 if (strcmp (peer->update_if, ifname) == 0)
2676 continue;
2677
2678 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2679 peer->update_if = NULL;
2680 }
2681
2682 if (peer->update_source)
2683 {
2684 sockunion_free (peer->update_source);
2685 peer->update_source = NULL;
2686 }
2687
2688 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2689
2690 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002691 {
2692 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2693 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2694 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2695 }
paul718e3742002-12-13 20:15:29 +00002696 else
2697 BGP_EVENT_ADD (peer, BGP_Stop);
2698 }
2699 return 0;
2700}
2701
2702int
2703peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2704{
2705 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002706 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002707
2708 if (peer->update_source)
2709 {
2710 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2711 && sockunion_cmp (peer->update_source, su) == 0)
2712 return 0;
2713 sockunion_free (peer->update_source);
2714 peer->update_source = NULL;
2715 }
2716
2717 if (peer->update_if)
2718 {
2719 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2720 peer->update_if = NULL;
2721 }
2722
2723 peer->update_source = sockunion_dup (su);
2724
2725 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2726 {
2727 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002728 {
2729 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2730 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2731 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2732 }
paul718e3742002-12-13 20:15:29 +00002733 else
2734 BGP_EVENT_ADD (peer, BGP_Stop);
2735 return 0;
2736 }
2737
2738 /* peer-group member updates. */
2739 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002740 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002741 {
2742 if (peer->update_source)
2743 {
2744 if (sockunion_cmp (peer->update_source, su) == 0)
2745 continue;
2746 sockunion_free (peer->update_source);
2747 peer->update_source = NULL;
2748 }
2749
2750 if (peer->update_if)
2751 {
2752 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2753 peer->update_if = NULL;
2754 }
2755
2756 peer->update_source = sockunion_dup (su);
2757
2758 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002759 {
2760 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2761 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2762 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2763 }
paul718e3742002-12-13 20:15:29 +00002764 else
2765 BGP_EVENT_ADD (peer, BGP_Stop);
2766 }
2767 return 0;
2768}
2769
2770int
2771peer_update_source_unset (struct peer *peer)
2772{
2773 union sockunion *su;
2774 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002775 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002776
2777 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2778 && ! peer->update_source
2779 && ! peer->update_if)
2780 return 0;
2781
2782 if (peer->update_source)
2783 {
2784 sockunion_free (peer->update_source);
2785 peer->update_source = NULL;
2786 }
2787 if (peer->update_if)
2788 {
2789 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2790 peer->update_if = NULL;
2791 }
2792
2793 if (peer_group_active (peer))
2794 {
2795 group = peer->group;
2796
2797 if (group->conf->update_source)
2798 {
2799 su = sockunion_dup (group->conf->update_source);
2800 peer->update_source = su;
2801 }
2802 else if (group->conf->update_if)
2803 peer->update_if =
2804 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2805 }
2806
2807 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2808 {
2809 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002810 {
2811 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2812 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2813 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2814 }
paul718e3742002-12-13 20:15:29 +00002815 else
2816 BGP_EVENT_ADD (peer, BGP_Stop);
2817 return 0;
2818 }
2819
2820 /* peer-group member updates. */
2821 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002822 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002823 {
2824 if (! peer->update_source && ! peer->update_if)
2825 continue;
2826
2827 if (peer->update_source)
2828 {
2829 sockunion_free (peer->update_source);
2830 peer->update_source = NULL;
2831 }
2832
2833 if (peer->update_if)
2834 {
2835 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2836 peer->update_if = NULL;
2837 }
2838
2839 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002840 {
2841 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2842 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2843 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2844 }
paul718e3742002-12-13 20:15:29 +00002845 else
2846 BGP_EVENT_ADD (peer, BGP_Stop);
2847 }
2848 return 0;
2849}
2850
2851int
2852peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002853 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002854{
2855 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002856 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002857
2858 /* Adress family must be activated. */
2859 if (! peer->afc[afi][safi])
2860 return BGP_ERR_PEER_INACTIVE;
2861
2862 /* Default originate can't be used for peer group memeber. */
2863 if (peer_is_group_member (peer, afi, safi))
2864 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2865
2866 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2867 || (rmap && ! peer->default_rmap[afi][safi].name)
2868 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2869 {
2870 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2871
2872 if (rmap)
2873 {
2874 if (peer->default_rmap[afi][safi].name)
2875 free (peer->default_rmap[afi][safi].name);
2876 peer->default_rmap[afi][safi].name = strdup (rmap);
2877 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2878 }
2879 }
2880
2881 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2882 {
2883 if (peer->status == Established && peer->afc_nego[afi][safi])
2884 bgp_default_originate (peer, afi, safi, 0);
2885 return 0;
2886 }
2887
2888 /* peer-group member updates. */
2889 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002890 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002891 {
2892 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2893
2894 if (rmap)
2895 {
2896 if (peer->default_rmap[afi][safi].name)
2897 free (peer->default_rmap[afi][safi].name);
2898 peer->default_rmap[afi][safi].name = strdup (rmap);
2899 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2900 }
2901
2902 if (peer->status == Established && peer->afc_nego[afi][safi])
2903 bgp_default_originate (peer, afi, safi, 0);
2904 }
2905 return 0;
2906}
2907
2908int
2909peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2910{
2911 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002912 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002913
2914 /* Adress family must be activated. */
2915 if (! peer->afc[afi][safi])
2916 return BGP_ERR_PEER_INACTIVE;
2917
2918 /* Default originate can't be used for peer group memeber. */
2919 if (peer_is_group_member (peer, afi, safi))
2920 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2921
2922 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2923 {
2924 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2925
2926 if (peer->default_rmap[afi][safi].name)
2927 free (peer->default_rmap[afi][safi].name);
2928 peer->default_rmap[afi][safi].name = NULL;
2929 peer->default_rmap[afi][safi].map = NULL;
2930 }
2931
2932 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2933 {
2934 if (peer->status == Established && peer->afc_nego[afi][safi])
2935 bgp_default_originate (peer, afi, safi, 1);
2936 return 0;
2937 }
2938
2939 /* peer-group member updates. */
2940 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002941 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002942 {
2943 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2944
2945 if (peer->default_rmap[afi][safi].name)
2946 free (peer->default_rmap[afi][safi].name);
2947 peer->default_rmap[afi][safi].name = NULL;
2948 peer->default_rmap[afi][safi].map = NULL;
2949
2950 if (peer->status == Established && peer->afc_nego[afi][safi])
2951 bgp_default_originate (peer, afi, safi, 1);
2952 }
2953 return 0;
2954}
2955
2956int
2957peer_port_set (struct peer *peer, u_int16_t port)
2958{
2959 peer->port = port;
2960 return 0;
2961}
2962
2963int
2964peer_port_unset (struct peer *peer)
2965{
2966 peer->port = BGP_PORT_DEFAULT;
2967 return 0;
2968}
2969
2970/* neighbor weight. */
2971int
2972peer_weight_set (struct peer *peer, u_int16_t weight)
2973{
2974 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002975 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002976
2977 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2978 peer->weight = weight;
2979
2980 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2981 return 0;
2982
2983 /* peer-group member updates. */
2984 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002985 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002986 {
2987 peer->weight = group->conf->weight;
2988 }
2989 return 0;
2990}
2991
2992int
2993peer_weight_unset (struct peer *peer)
2994{
2995 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002996 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002997
2998 /* Set default weight. */
2999 if (peer_group_active (peer))
3000 peer->weight = peer->group->conf->weight;
3001 else
3002 peer->weight = 0;
3003
3004 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3005
3006 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3007 return 0;
3008
3009 /* peer-group member updates. */
3010 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003011 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003012 {
3013 peer->weight = 0;
3014 }
3015 return 0;
3016}
3017
3018int
3019peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3020{
3021 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003022 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003023
3024 /* Not for peer group memeber. */
3025 if (peer_group_active (peer))
3026 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3027
3028 /* keepalive value check. */
3029 if (keepalive > 65535)
3030 return BGP_ERR_INVALID_VALUE;
3031
3032 /* Holdtime value check. */
3033 if (holdtime > 65535)
3034 return BGP_ERR_INVALID_VALUE;
3035
3036 /* Holdtime value must be either 0 or greater than 3. */
3037 if (holdtime < 3 && holdtime != 0)
3038 return BGP_ERR_INVALID_VALUE;
3039
3040 /* Set value to the configuration. */
3041 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3042 peer->holdtime = holdtime;
3043 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3044
3045 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3046 return 0;
3047
3048 /* peer-group member updates. */
3049 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003050 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003051 {
3052 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3053 peer->holdtime = group->conf->holdtime;
3054 peer->keepalive = group->conf->keepalive;
3055 }
3056 return 0;
3057}
3058
3059int
3060peer_timers_unset (struct peer *peer)
3061{
3062 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003063 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003064
3065 if (peer_group_active (peer))
3066 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3067
3068 /* Clear configuration. */
3069 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3070 peer->keepalive = 0;
3071 peer->holdtime = 0;
3072
3073 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3074 return 0;
3075
3076 /* peer-group member updates. */
3077 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003079 {
3080 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3081 peer->holdtime = 0;
3082 peer->keepalive = 0;
3083 }
3084
3085 return 0;
3086}
3087
3088int
3089peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3090{
3091 if (peer_group_active (peer))
3092 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3093
3094 if (connect > 65535)
3095 return BGP_ERR_INVALID_VALUE;
3096
3097 /* Set value to the configuration. */
3098 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3099 peer->connect = connect;
3100
3101 /* Set value to timer setting. */
3102 peer->v_connect = connect;
3103
3104 return 0;
3105}
3106
3107int
3108peer_timers_connect_unset (struct peer *peer)
3109{
3110 if (peer_group_active (peer))
3111 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3112
3113 /* Clear configuration. */
3114 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3115 peer->connect = 0;
3116
3117 /* Set timer setting to default value. */
3118 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3119
3120 return 0;
3121}
3122
3123int
3124peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3125{
3126 if (peer_group_active (peer))
3127 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3128
3129 if (routeadv > 600)
3130 return BGP_ERR_INVALID_VALUE;
3131
3132 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3133 peer->routeadv = routeadv;
3134 peer->v_routeadv = routeadv;
3135
3136 return 0;
3137}
3138
3139int
3140peer_advertise_interval_unset (struct peer *peer)
3141{
3142 if (peer_group_active (peer))
3143 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3144
3145 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3146 peer->routeadv = 0;
3147
3148 if (peer_sort (peer) == BGP_PEER_IBGP)
3149 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3150 else
3151 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3152
3153 return 0;
3154}
3155
paul718e3742002-12-13 20:15:29 +00003156/* neighbor interface */
3157int
paulfd79ac92004-10-13 05:06:08 +00003158peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003159{
3160 if (peer->ifname)
3161 free (peer->ifname);
3162 peer->ifname = strdup (str);
3163
3164 return 0;
3165}
3166
3167int
3168peer_interface_unset (struct peer *peer)
3169{
3170 if (peer->ifname)
3171 free (peer->ifname);
3172 peer->ifname = NULL;
3173
3174 return 0;
3175}
3176
3177/* Allow-as in. */
3178int
3179peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3180{
3181 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003182 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003183
3184 if (allow_num < 1 || allow_num > 10)
3185 return BGP_ERR_INVALID_VALUE;
3186
3187 if (peer->allowas_in[afi][safi] != allow_num)
3188 {
3189 peer->allowas_in[afi][safi] = allow_num;
3190 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3191 peer_change_action (peer, afi, safi, peer_change_reset_in);
3192 }
3193
3194 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3195 return 0;
3196
3197 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003198 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003199 {
3200 if (peer->allowas_in[afi][safi] != allow_num)
3201 {
3202 peer->allowas_in[afi][safi] = allow_num;
3203 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3204 peer_change_action (peer, afi, safi, peer_change_reset_in);
3205 }
3206
3207 }
3208 return 0;
3209}
3210
3211int
3212peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3213{
3214 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003215 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003216
3217 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3218 {
3219 peer->allowas_in[afi][safi] = 0;
3220 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3221 }
3222
3223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3224 return 0;
3225
3226 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003227 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003228 {
3229 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3230 {
3231 peer->allowas_in[afi][safi] = 0;
3232 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3233 }
3234 }
3235 return 0;
3236}
3237
3238int
3239peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3240{
3241 struct bgp *bgp = peer->bgp;
3242 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003243 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003244
3245 if (peer_sort (peer) != BGP_PEER_EBGP
3246 && peer_sort (peer) != BGP_PEER_INTERNAL)
3247 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3248
3249 if (bgp->as == as)
3250 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3251
3252 if (peer_group_active (peer))
3253 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3254
3255 if (peer->change_local_as == as &&
3256 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3257 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3258 return 0;
3259
3260 peer->change_local_as = as;
3261 if (no_prepend)
3262 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3263 else
3264 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3265
3266 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3267 {
3268 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003269 {
3270 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3271 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3272 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3273 }
paul718e3742002-12-13 20:15:29 +00003274 else
3275 BGP_EVENT_ADD (peer, BGP_Stop);
3276
3277 return 0;
3278 }
3279
3280 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003281 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003282 {
3283 peer->change_local_as = as;
3284 if (no_prepend)
3285 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3286 else
3287 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3288
3289 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003290 {
3291 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3292 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3293 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3294 }
paul718e3742002-12-13 20:15:29 +00003295 else
3296 BGP_EVENT_ADD (peer, BGP_Stop);
3297 }
3298
3299 return 0;
3300}
3301
3302int
3303peer_local_as_unset (struct peer *peer)
3304{
3305 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003306 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003307
3308 if (peer_group_active (peer))
3309 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3310
3311 if (! peer->change_local_as)
3312 return 0;
3313
3314 peer->change_local_as = 0;
3315 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3316
3317 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3318 {
3319 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003320 {
3321 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3322 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3323 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3324 }
paul718e3742002-12-13 20:15:29 +00003325 else
3326 BGP_EVENT_ADD (peer, BGP_Stop);
3327
3328 return 0;
3329 }
3330
3331 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003332 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003333 {
3334 peer->change_local_as = 0;
3335 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3336
3337 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003338 {
3339 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3340 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3341 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3342 }
paul718e3742002-12-13 20:15:29 +00003343 else
3344 BGP_EVENT_ADD (peer, BGP_Stop);
3345 }
3346 return 0;
3347}
3348
3349/* Set distribute list to the peer. */
3350int
3351peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003352 const char *name)
paul718e3742002-12-13 20:15:29 +00003353{
3354 struct bgp_filter *filter;
3355 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003356 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003357
3358 if (! peer->afc[afi][safi])
3359 return BGP_ERR_PEER_INACTIVE;
3360
3361 if (direct != FILTER_IN && direct != FILTER_OUT)
3362 return BGP_ERR_INVALID_VALUE;
3363
3364 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3365 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3366
3367 filter = &peer->filter[afi][safi];
3368
3369 if (filter->plist[direct].name)
3370 return BGP_ERR_PEER_FILTER_CONFLICT;
3371
3372 if (filter->dlist[direct].name)
3373 free (filter->dlist[direct].name);
3374 filter->dlist[direct].name = strdup (name);
3375 filter->dlist[direct].alist = access_list_lookup (afi, name);
3376
3377 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3378 return 0;
3379
3380 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003381 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003382 {
3383 filter = &peer->filter[afi][safi];
3384
3385 if (! peer->af_group[afi][safi])
3386 continue;
3387
3388 if (filter->dlist[direct].name)
3389 free (filter->dlist[direct].name);
3390 filter->dlist[direct].name = strdup (name);
3391 filter->dlist[direct].alist = access_list_lookup (afi, name);
3392 }
3393
3394 return 0;
3395}
3396
3397int
3398peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3399{
3400 struct bgp_filter *filter;
3401 struct bgp_filter *gfilter;
3402 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003403 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003404
3405 if (! peer->afc[afi][safi])
3406 return BGP_ERR_PEER_INACTIVE;
3407
3408 if (direct != FILTER_IN && direct != FILTER_OUT)
3409 return BGP_ERR_INVALID_VALUE;
3410
3411 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3412 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3413
3414 filter = &peer->filter[afi][safi];
3415
3416 /* apply peer-group filter */
3417 if (peer->af_group[afi][safi])
3418 {
3419 gfilter = &peer->group->conf->filter[afi][safi];
3420
3421 if (gfilter->dlist[direct].name)
3422 {
3423 if (filter->dlist[direct].name)
3424 free (filter->dlist[direct].name);
3425 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3426 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3427 return 0;
3428 }
3429 }
3430
3431 if (filter->dlist[direct].name)
3432 free (filter->dlist[direct].name);
3433 filter->dlist[direct].name = NULL;
3434 filter->dlist[direct].alist = NULL;
3435
3436 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3437 return 0;
3438
3439 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003440 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003441 {
3442 filter = &peer->filter[afi][safi];
3443
3444 if (! peer->af_group[afi][safi])
3445 continue;
3446
3447 if (filter->dlist[direct].name)
3448 free (filter->dlist[direct].name);
3449 filter->dlist[direct].name = NULL;
3450 filter->dlist[direct].alist = NULL;
3451 }
3452
3453 return 0;
3454}
3455
3456/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003457static void
paul718e3742002-12-13 20:15:29 +00003458peer_distribute_update (struct access_list *access)
3459{
3460 afi_t afi;
3461 safi_t safi;
3462 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003463 struct listnode *mnode, *mnnode;
3464 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003465 struct bgp *bgp;
3466 struct peer *peer;
3467 struct peer_group *group;
3468 struct bgp_filter *filter;
3469
paul1eb8ef22005-04-07 07:30:20 +00003470 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003471 {
paul1eb8ef22005-04-07 07:30:20 +00003472 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003473 {
3474 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3475 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3476 {
3477 filter = &peer->filter[afi][safi];
3478
3479 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3480 {
3481 if (filter->dlist[direct].name)
3482 filter->dlist[direct].alist =
3483 access_list_lookup (afi, filter->dlist[direct].name);
3484 else
3485 filter->dlist[direct].alist = NULL;
3486 }
3487 }
3488 }
paul1eb8ef22005-04-07 07:30:20 +00003489 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003490 {
3491 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3492 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3493 {
3494 filter = &group->conf->filter[afi][safi];
3495
3496 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3497 {
3498 if (filter->dlist[direct].name)
3499 filter->dlist[direct].alist =
3500 access_list_lookup (afi, filter->dlist[direct].name);
3501 else
3502 filter->dlist[direct].alist = NULL;
3503 }
3504 }
3505 }
3506 }
3507}
3508
3509/* Set prefix list to the peer. */
3510int
3511peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003512 const char *name)
paul718e3742002-12-13 20:15:29 +00003513{
3514 struct bgp_filter *filter;
3515 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003516 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003517
3518 if (! peer->afc[afi][safi])
3519 return BGP_ERR_PEER_INACTIVE;
3520
3521 if (direct != FILTER_IN && direct != FILTER_OUT)
3522 return BGP_ERR_INVALID_VALUE;
3523
3524 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3525 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3526
3527 filter = &peer->filter[afi][safi];
3528
3529 if (filter->dlist[direct].name)
3530 return BGP_ERR_PEER_FILTER_CONFLICT;
3531
3532 if (filter->plist[direct].name)
3533 free (filter->plist[direct].name);
3534 filter->plist[direct].name = strdup (name);
3535 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3536
3537 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3538 return 0;
3539
3540 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003541 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003542 {
3543 filter = &peer->filter[afi][safi];
3544
3545 if (! peer->af_group[afi][safi])
3546 continue;
3547
3548 if (filter->plist[direct].name)
3549 free (filter->plist[direct].name);
3550 filter->plist[direct].name = strdup (name);
3551 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3552 }
3553 return 0;
3554}
3555
3556int
3557peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3558{
3559 struct bgp_filter *filter;
3560 struct bgp_filter *gfilter;
3561 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003562 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003563
3564 if (! peer->afc[afi][safi])
3565 return BGP_ERR_PEER_INACTIVE;
3566
3567 if (direct != FILTER_IN && direct != FILTER_OUT)
3568 return BGP_ERR_INVALID_VALUE;
3569
3570 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3571 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3572
3573 filter = &peer->filter[afi][safi];
3574
3575 /* apply peer-group filter */
3576 if (peer->af_group[afi][safi])
3577 {
3578 gfilter = &peer->group->conf->filter[afi][safi];
3579
3580 if (gfilter->plist[direct].name)
3581 {
3582 if (filter->plist[direct].name)
3583 free (filter->plist[direct].name);
3584 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3585 filter->plist[direct].plist = gfilter->plist[direct].plist;
3586 return 0;
3587 }
3588 }
3589
3590 if (filter->plist[direct].name)
3591 free (filter->plist[direct].name);
3592 filter->plist[direct].name = NULL;
3593 filter->plist[direct].plist = NULL;
3594
3595 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3596 return 0;
3597
3598 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003599 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003600 {
3601 filter = &peer->filter[afi][safi];
3602
3603 if (! peer->af_group[afi][safi])
3604 continue;
3605
3606 if (filter->plist[direct].name)
3607 free (filter->plist[direct].name);
3608 filter->plist[direct].name = NULL;
3609 filter->plist[direct].plist = NULL;
3610 }
3611
3612 return 0;
3613}
3614
3615/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003616static void
paul718e3742002-12-13 20:15:29 +00003617peer_prefix_list_update (struct prefix_list *plist)
3618{
paul1eb8ef22005-04-07 07:30:20 +00003619 struct listnode *mnode, *mnnode;
3620 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003621 struct bgp *bgp;
3622 struct peer *peer;
3623 struct peer_group *group;
3624 struct bgp_filter *filter;
3625 afi_t afi;
3626 safi_t safi;
3627 int direct;
3628
paul1eb8ef22005-04-07 07:30:20 +00003629 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003630 {
paul1eb8ef22005-04-07 07:30:20 +00003631 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003632 {
3633 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3634 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3635 {
3636 filter = &peer->filter[afi][safi];
3637
3638 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3639 {
3640 if (filter->plist[direct].name)
3641 filter->plist[direct].plist =
3642 prefix_list_lookup (afi, filter->plist[direct].name);
3643 else
3644 filter->plist[direct].plist = NULL;
3645 }
3646 }
3647 }
paul1eb8ef22005-04-07 07:30:20 +00003648 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003649 {
3650 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3651 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3652 {
3653 filter = &group->conf->filter[afi][safi];
3654
3655 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3656 {
3657 if (filter->plist[direct].name)
3658 filter->plist[direct].plist =
3659 prefix_list_lookup (afi, filter->plist[direct].name);
3660 else
3661 filter->plist[direct].plist = NULL;
3662 }
3663 }
3664 }
3665 }
3666}
3667
3668int
3669peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003670 const char *name)
paul718e3742002-12-13 20:15:29 +00003671{
3672 struct bgp_filter *filter;
3673 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003674 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003675
3676 if (! peer->afc[afi][safi])
3677 return BGP_ERR_PEER_INACTIVE;
3678
3679 if (direct != FILTER_IN && direct != FILTER_OUT)
3680 return BGP_ERR_INVALID_VALUE;
3681
3682 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3683 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3684
3685 filter = &peer->filter[afi][safi];
3686
3687 if (filter->aslist[direct].name)
3688 free (filter->aslist[direct].name);
3689 filter->aslist[direct].name = strdup (name);
3690 filter->aslist[direct].aslist = as_list_lookup (name);
3691
3692 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3693 return 0;
3694
3695 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003696 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003697 {
3698 filter = &peer->filter[afi][safi];
3699
3700 if (! peer->af_group[afi][safi])
3701 continue;
3702
3703 if (filter->aslist[direct].name)
3704 free (filter->aslist[direct].name);
3705 filter->aslist[direct].name = strdup (name);
3706 filter->aslist[direct].aslist = as_list_lookup (name);
3707 }
3708 return 0;
3709}
3710
3711int
3712peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3713{
3714 struct bgp_filter *filter;
3715 struct bgp_filter *gfilter;
3716 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003717 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003718
3719 if (! peer->afc[afi][safi])
3720 return BGP_ERR_PEER_INACTIVE;
3721
hassob5f29602005-05-25 21:00:28 +00003722 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003723 return BGP_ERR_INVALID_VALUE;
3724
hassob5f29602005-05-25 21:00:28 +00003725 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003726 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3727
3728 filter = &peer->filter[afi][safi];
3729
3730 /* apply peer-group filter */
3731 if (peer->af_group[afi][safi])
3732 {
3733 gfilter = &peer->group->conf->filter[afi][safi];
3734
3735 if (gfilter->aslist[direct].name)
3736 {
3737 if (filter->aslist[direct].name)
3738 free (filter->aslist[direct].name);
3739 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3740 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3741 return 0;
3742 }
3743 }
3744
3745 if (filter->aslist[direct].name)
3746 free (filter->aslist[direct].name);
3747 filter->aslist[direct].name = NULL;
3748 filter->aslist[direct].aslist = NULL;
3749
3750 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3751 return 0;
3752
3753 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003754 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003755 {
3756 filter = &peer->filter[afi][safi];
3757
3758 if (! peer->af_group[afi][safi])
3759 continue;
3760
3761 if (filter->aslist[direct].name)
3762 free (filter->aslist[direct].name);
3763 filter->aslist[direct].name = NULL;
3764 filter->aslist[direct].aslist = NULL;
3765 }
3766
3767 return 0;
3768}
3769
paul94f2b392005-06-28 12:44:16 +00003770static void
paul718e3742002-12-13 20:15:29 +00003771peer_aslist_update ()
3772{
3773 afi_t afi;
3774 safi_t safi;
3775 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003776 struct listnode *mnode, *mnnode;
3777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003778 struct bgp *bgp;
3779 struct peer *peer;
3780 struct peer_group *group;
3781 struct bgp_filter *filter;
3782
paul1eb8ef22005-04-07 07:30:20 +00003783 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003784 {
paul1eb8ef22005-04-07 07:30:20 +00003785 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003786 {
3787 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3788 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3789 {
3790 filter = &peer->filter[afi][safi];
3791
3792 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3793 {
3794 if (filter->aslist[direct].name)
3795 filter->aslist[direct].aslist =
3796 as_list_lookup (filter->aslist[direct].name);
3797 else
3798 filter->aslist[direct].aslist = NULL;
3799 }
3800 }
3801 }
paul1eb8ef22005-04-07 07:30:20 +00003802 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003803 {
3804 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3805 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3806 {
3807 filter = &group->conf->filter[afi][safi];
3808
3809 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3810 {
3811 if (filter->aslist[direct].name)
3812 filter->aslist[direct].aslist =
3813 as_list_lookup (filter->aslist[direct].name);
3814 else
3815 filter->aslist[direct].aslist = NULL;
3816 }
3817 }
3818 }
3819 }
3820}
3821
3822/* Set route-map to the peer. */
3823int
3824peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003825 const char *name)
paul718e3742002-12-13 20:15:29 +00003826{
3827 struct bgp_filter *filter;
3828 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003829 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003830
3831 if (! peer->afc[afi][safi])
3832 return BGP_ERR_PEER_INACTIVE;
3833
paulfee0f4c2004-09-13 05:12:46 +00003834 if (direct != RMAP_IN && direct != RMAP_OUT &&
3835 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003836 return BGP_ERR_INVALID_VALUE;
3837
paulfee0f4c2004-09-13 05:12:46 +00003838 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3839 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003840 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3841
3842 filter = &peer->filter[afi][safi];
3843
3844 if (filter->map[direct].name)
3845 free (filter->map[direct].name);
3846
3847 filter->map[direct].name = strdup (name);
3848 filter->map[direct].map = route_map_lookup_by_name (name);
3849
3850 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3851 return 0;
3852
3853 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003854 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003855 {
3856 filter = &peer->filter[afi][safi];
3857
3858 if (! peer->af_group[afi][safi])
3859 continue;
3860
3861 if (filter->map[direct].name)
3862 free (filter->map[direct].name);
3863 filter->map[direct].name = strdup (name);
3864 filter->map[direct].map = route_map_lookup_by_name (name);
3865 }
3866 return 0;
3867}
3868
3869/* Unset route-map from the peer. */
3870int
3871peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3872{
3873 struct bgp_filter *filter;
3874 struct bgp_filter *gfilter;
3875 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003876 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003877
3878 if (! peer->afc[afi][safi])
3879 return BGP_ERR_PEER_INACTIVE;
3880
hassob5f29602005-05-25 21:00:28 +00003881 if (direct != RMAP_IN && direct != RMAP_OUT &&
3882 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003883 return BGP_ERR_INVALID_VALUE;
3884
hassob5f29602005-05-25 21:00:28 +00003885 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3886 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003887 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3888
3889 filter = &peer->filter[afi][safi];
3890
3891 /* apply peer-group filter */
3892 if (peer->af_group[afi][safi])
3893 {
3894 gfilter = &peer->group->conf->filter[afi][safi];
3895
3896 if (gfilter->map[direct].name)
3897 {
3898 if (filter->map[direct].name)
3899 free (filter->map[direct].name);
3900 filter->map[direct].name = strdup (gfilter->map[direct].name);
3901 filter->map[direct].map = gfilter->map[direct].map;
3902 return 0;
3903 }
3904 }
3905
3906 if (filter->map[direct].name)
3907 free (filter->map[direct].name);
3908 filter->map[direct].name = NULL;
3909 filter->map[direct].map = NULL;
3910
3911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3912 return 0;
3913
3914 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003915 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003916 {
3917 filter = &peer->filter[afi][safi];
3918
3919 if (! peer->af_group[afi][safi])
3920 continue;
3921
3922 if (filter->map[direct].name)
3923 free (filter->map[direct].name);
3924 filter->map[direct].name = NULL;
3925 filter->map[direct].map = NULL;
3926 }
3927 return 0;
3928}
3929
3930/* Set unsuppress-map to the peer. */
3931int
paulfd79ac92004-10-13 05:06:08 +00003932peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3933 const char *name)
paul718e3742002-12-13 20:15:29 +00003934{
3935 struct bgp_filter *filter;
3936 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003937 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003938
3939 if (! peer->afc[afi][safi])
3940 return BGP_ERR_PEER_INACTIVE;
3941
3942 if (peer_is_group_member (peer, afi, safi))
3943 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3944
3945 filter = &peer->filter[afi][safi];
3946
3947 if (filter->usmap.name)
3948 free (filter->usmap.name);
3949
3950 filter->usmap.name = strdup (name);
3951 filter->usmap.map = route_map_lookup_by_name (name);
3952
3953 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3954 return 0;
3955
3956 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003957 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003958 {
3959 filter = &peer->filter[afi][safi];
3960
3961 if (! peer->af_group[afi][safi])
3962 continue;
3963
3964 if (filter->usmap.name)
3965 free (filter->usmap.name);
3966 filter->usmap.name = strdup (name);
3967 filter->usmap.map = route_map_lookup_by_name (name);
3968 }
3969 return 0;
3970}
3971
3972/* Unset route-map from the peer. */
3973int
3974peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3975{
3976 struct bgp_filter *filter;
3977 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003978 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003979
3980 if (! peer->afc[afi][safi])
3981 return BGP_ERR_PEER_INACTIVE;
3982
3983 if (peer_is_group_member (peer, afi, safi))
3984 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3985
3986 filter = &peer->filter[afi][safi];
3987
3988 if (filter->usmap.name)
3989 free (filter->usmap.name);
3990 filter->usmap.name = NULL;
3991 filter->usmap.map = NULL;
3992
3993 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3994 return 0;
3995
3996 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003997 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003998 {
3999 filter = &peer->filter[afi][safi];
4000
4001 if (! peer->af_group[afi][safi])
4002 continue;
4003
4004 if (filter->usmap.name)
4005 free (filter->usmap.name);
4006 filter->usmap.name = NULL;
4007 filter->usmap.map = NULL;
4008 }
4009 return 0;
4010}
4011
4012int
4013peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004014 u_int32_t max, u_char threshold,
4015 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004016{
4017 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004018 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004019
4020 if (! peer->afc[afi][safi])
4021 return BGP_ERR_PEER_INACTIVE;
4022
4023 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4024 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004025 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004026 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004027 if (warning)
4028 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4029 else
4030 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4031
4032 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4033 return 0;
4034
4035 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004036 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004037 {
4038 if (! peer->af_group[afi][safi])
4039 continue;
4040
4041 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4042 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004043 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004044 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004045 if (warning)
4046 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4047 else
4048 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4049 }
4050 return 0;
4051}
4052
4053int
4054peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4055{
4056 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004057 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004058
4059 if (! peer->afc[afi][safi])
4060 return BGP_ERR_PEER_INACTIVE;
4061
4062 /* apply peer-group config */
4063 if (peer->af_group[afi][safi])
4064 {
4065 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4066 PEER_FLAG_MAX_PREFIX))
4067 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4068 else
4069 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4070
4071 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4072 PEER_FLAG_MAX_PREFIX_WARNING))
4073 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4074 else
4075 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4076
4077 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004078 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004079 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004080 return 0;
4081 }
4082
4083 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4084 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4085 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004086 peer->pmax_threshold[afi][safi] = 0;
4087 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004088
4089 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4090 return 0;
4091
4092 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004093 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004094 {
4095 if (! peer->af_group[afi][safi])
4096 continue;
4097
4098 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4099 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4100 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004101 peer->pmax_threshold[afi][safi] = 0;
4102 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004103 }
4104 return 0;
4105}
4106
4107int
4108peer_clear (struct peer *peer)
4109{
4110 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4111 {
hasso0a486e52005-02-01 20:57:17 +00004112 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4113 {
4114 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4115 if (peer->t_pmax_restart)
4116 {
4117 BGP_TIMER_OFF (peer->t_pmax_restart);
4118 if (BGP_DEBUG (events, EVENTS))
4119 zlog_debug ("%s Maximum-prefix restart timer canceled",
4120 peer->host);
4121 }
4122 BGP_EVENT_ADD (peer, BGP_Start);
4123 return 0;
4124 }
4125
paul718e3742002-12-13 20:15:29 +00004126 peer->v_start = BGP_INIT_START_TIMER;
4127 if (peer->status == Established)
4128 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4129 BGP_NOTIFY_CEASE_ADMIN_RESET);
4130 else
4131 BGP_EVENT_ADD (peer, BGP_Stop);
4132 }
4133 return 0;
4134}
4135
4136int
4137peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4138 enum bgp_clear_type stype)
4139{
4140 if (peer->status != Established)
4141 return 0;
4142
4143 if (! peer->afc[afi][safi])
4144 return BGP_ERR_AF_UNCONFIGURED;
4145
paulfee0f4c2004-09-13 05:12:46 +00004146 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4147 {
4148 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4149 return 0;
4150 bgp_check_local_routes_rsclient (peer, afi, safi);
4151 bgp_soft_reconfig_rsclient (peer, afi, safi);
4152 }
4153
paul718e3742002-12-13 20:15:29 +00004154 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4155 bgp_announce_route (peer, afi, safi);
4156
4157 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4158 {
4159 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4160 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4161 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4162 {
4163 struct bgp_filter *filter = &peer->filter[afi][safi];
4164 u_char prefix_type;
4165
4166 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4167 prefix_type = ORF_TYPE_PREFIX;
4168 else
4169 prefix_type = ORF_TYPE_PREFIX_OLD;
4170
4171 if (filter->plist[FILTER_IN].plist)
4172 {
4173 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4174 bgp_route_refresh_send (peer, afi, safi,
4175 prefix_type, REFRESH_DEFER, 1);
4176 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4177 REFRESH_IMMEDIATE, 0);
4178 }
4179 else
4180 {
4181 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4182 bgp_route_refresh_send (peer, afi, safi,
4183 prefix_type, REFRESH_IMMEDIATE, 1);
4184 else
4185 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4186 }
4187 return 0;
4188 }
4189 }
4190
4191 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4192 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4193 {
4194 /* If neighbor has soft reconfiguration inbound flag.
4195 Use Adj-RIB-In database. */
4196 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4197 bgp_soft_reconfig_in (peer, afi, safi);
4198 else
4199 {
4200 /* If neighbor has route refresh capability, send route refresh
4201 message to the peer. */
4202 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4203 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4204 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4205 else
4206 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4207 }
4208 }
4209 return 0;
4210}
4211
paulfd79ac92004-10-13 05:06:08 +00004212/* Display peer uptime.*/
4213/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004214char *
4215peer_uptime (time_t uptime2, char *buf, size_t len)
4216{
4217 time_t uptime1;
4218 struct tm *tm;
4219
4220 /* Check buffer length. */
4221 if (len < BGP_UPTIME_LEN)
4222 {
gdtc29fdba2004-12-09 14:46:46 +00004223 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004224 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004225 /* XXX: should return status instead of buf... */
4226 snprintf (buf, len, "<error> ");
4227 return buf;
paul718e3742002-12-13 20:15:29 +00004228 }
4229
4230 /* If there is no connection has been done before print `never'. */
4231 if (uptime2 == 0)
4232 {
4233 snprintf (buf, len, "never ");
4234 return buf;
4235 }
4236
4237 /* Get current time. */
4238 uptime1 = time (NULL);
4239 uptime1 -= uptime2;
4240 tm = gmtime (&uptime1);
4241
4242 /* Making formatted timer strings. */
4243#define ONE_DAY_SECOND 60*60*24
4244#define ONE_WEEK_SECOND 60*60*24*7
4245
4246 if (uptime1 < ONE_DAY_SECOND)
4247 snprintf (buf, len, "%02d:%02d:%02d",
4248 tm->tm_hour, tm->tm_min, tm->tm_sec);
4249 else if (uptime1 < ONE_WEEK_SECOND)
4250 snprintf (buf, len, "%dd%02dh%02dm",
4251 tm->tm_yday, tm->tm_hour, tm->tm_min);
4252 else
4253 snprintf (buf, len, "%02dw%dd%02dh",
4254 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4255 return buf;
4256}
4257
paul94f2b392005-06-28 12:44:16 +00004258static void
paul718e3742002-12-13 20:15:29 +00004259bgp_config_write_filter (struct vty *vty, struct peer *peer,
4260 afi_t afi, safi_t safi)
4261{
4262 struct bgp_filter *filter;
4263 struct bgp_filter *gfilter = NULL;
4264 char *addr;
4265 int in = FILTER_IN;
4266 int out = FILTER_OUT;
4267
4268 addr = peer->host;
4269 filter = &peer->filter[afi][safi];
4270 if (peer->af_group[afi][safi])
4271 gfilter = &peer->group->conf->filter[afi][safi];
4272
4273 /* distribute-list. */
4274 if (filter->dlist[in].name)
4275 if (! gfilter || ! gfilter->dlist[in].name
4276 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4277 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4278 filter->dlist[in].name, VTY_NEWLINE);
4279 if (filter->dlist[out].name && ! gfilter)
4280 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4281 filter->dlist[out].name, VTY_NEWLINE);
4282
4283 /* prefix-list. */
4284 if (filter->plist[in].name)
4285 if (! gfilter || ! gfilter->plist[in].name
4286 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4287 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4288 filter->plist[in].name, VTY_NEWLINE);
4289 if (filter->plist[out].name && ! gfilter)
4290 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4291 filter->plist[out].name, VTY_NEWLINE);
4292
4293 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004294 if (filter->map[RMAP_IN].name)
4295 if (! gfilter || ! gfilter->map[RMAP_IN].name
4296 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004297 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004298 filter->map[RMAP_IN].name, VTY_NEWLINE);
4299 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004300 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004301 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4302 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4303 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4304 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4305 if (filter->map[RMAP_EXPORT].name)
4306 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4307 || strcmp (filter->map[RMAP_EXPORT].name,
4308 gfilter->map[RMAP_EXPORT].name) != 0)
4309 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4310 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004311
4312 /* unsuppress-map */
4313 if (filter->usmap.name && ! gfilter)
4314 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4315 filter->usmap.name, VTY_NEWLINE);
4316
4317 /* filter-list. */
4318 if (filter->aslist[in].name)
4319 if (! gfilter || ! gfilter->aslist[in].name
4320 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4321 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4322 filter->aslist[in].name, VTY_NEWLINE);
4323 if (filter->aslist[out].name && ! gfilter)
4324 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4325 filter->aslist[out].name, VTY_NEWLINE);
4326}
4327
4328/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004329static void
paul718e3742002-12-13 20:15:29 +00004330bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4331 struct peer *peer, afi_t afi, safi_t safi)
4332{
4333 struct bgp_filter *filter;
4334 struct peer *g_peer = NULL;
4335 char buf[SU_ADDRSTRLEN];
4336 char *addr;
4337
4338 filter = &peer->filter[afi][safi];
4339 addr = peer->host;
4340 if (peer_group_active (peer))
4341 g_peer = peer->group->conf;
4342
4343 /************************************
4344 ****** Global to the neighbor ******
4345 ************************************/
4346 if (afi == AFI_IP && safi == SAFI_UNICAST)
4347 {
4348 /* remote-as. */
4349 if (! peer_group_active (peer))
4350 {
4351 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4352 vty_out (vty, " neighbor %s peer-group%s", addr,
4353 VTY_NEWLINE);
4354 if (peer->as)
4355 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4356 VTY_NEWLINE);
4357 }
4358 else
4359 {
4360 if (! g_peer->as)
4361 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4362 VTY_NEWLINE);
4363 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4364 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4365 peer->group->name, VTY_NEWLINE);
4366 }
4367
4368 /* local-as. */
4369 if (peer->change_local_as)
4370 if (! peer_group_active (peer))
4371 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4372 peer->change_local_as,
4373 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4374 " no-prepend" : "", VTY_NEWLINE);
4375
4376 /* Description. */
4377 if (peer->desc)
4378 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4379 VTY_NEWLINE);
4380
4381 /* Shutdown. */
4382 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4383 if (! peer_group_active (peer) ||
4384 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4385 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4386
4387 /* BGP port. */
4388 if (peer->port != BGP_PORT_DEFAULT)
4389 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4390 VTY_NEWLINE);
4391
4392 /* Local interface name. */
4393 if (peer->ifname)
4394 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4395 VTY_NEWLINE);
4396
4397 /* Passive. */
4398 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4399 if (! peer_group_active (peer) ||
4400 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4401 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4402
4403 /* EBGP multihop. */
4404 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4405 if (! peer_group_active (peer) ||
4406 g_peer->ttl != peer->ttl)
4407 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4408 VTY_NEWLINE);
4409
hasso6ffd2072005-02-02 14:50:11 +00004410 /* disable-connected-check. */
4411 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004412 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004413 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4414 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004415
4416 /* Update-source. */
4417 if (peer->update_if)
4418 if (! peer_group_active (peer) || ! g_peer->update_if
4419 || strcmp (g_peer->update_if, peer->update_if) != 0)
4420 vty_out (vty, " neighbor %s update-source %s%s", addr,
4421 peer->update_if, VTY_NEWLINE);
4422 if (peer->update_source)
4423 if (! peer_group_active (peer) || ! g_peer->update_source
4424 || sockunion_cmp (g_peer->update_source,
4425 peer->update_source) != 0)
4426 vty_out (vty, " neighbor %s update-source %s%s", addr,
4427 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4428 VTY_NEWLINE);
4429
paul718e3742002-12-13 20:15:29 +00004430 /* advertisement-interval */
4431 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4432 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4433 addr, peer->v_routeadv, VTY_NEWLINE);
4434
4435 /* timers. */
4436 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4437 && ! peer_group_active (peer))
4438 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4439 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4440
4441 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4442 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4443 peer->connect, VTY_NEWLINE);
4444
4445 /* Default weight. */
4446 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4447 if (! peer_group_active (peer) ||
4448 g_peer->weight != peer->weight)
4449 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4450 VTY_NEWLINE);
4451
paul718e3742002-12-13 20:15:29 +00004452 /* Dynamic capability. */
4453 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4454 if (! peer_group_active (peer) ||
4455 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4456 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4457 VTY_NEWLINE);
4458
4459 /* dont capability negotiation. */
4460 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4461 if (! peer_group_active (peer) ||
4462 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4463 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4464 VTY_NEWLINE);
4465
4466 /* override capability negotiation. */
4467 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4468 if (! peer_group_active (peer) ||
4469 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4470 vty_out (vty, " neighbor %s override-capability%s", addr,
4471 VTY_NEWLINE);
4472
4473 /* strict capability negotiation. */
4474 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4475 if (! peer_group_active (peer) ||
4476 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4477 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4478 VTY_NEWLINE);
4479
4480 if (! peer_group_active (peer))
4481 {
4482 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4483 {
4484 if (peer->afc[AFI_IP][SAFI_UNICAST])
4485 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4486 }
4487 else
4488 {
4489 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4490 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4491 }
4492 }
4493 }
4494
4495
4496 /************************************
4497 ****** Per AF to the neighbor ******
4498 ************************************/
4499
4500 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4501 {
4502 if (peer->af_group[afi][safi])
4503 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4504 peer->group->name, VTY_NEWLINE);
4505 else
4506 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4507 }
4508
4509 /* ORF capability. */
4510 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4511 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4512 if (! peer->af_group[afi][safi])
4513 {
4514 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4515
4516 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4517 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4518 vty_out (vty, " both");
4519 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4520 vty_out (vty, " send");
4521 else
4522 vty_out (vty, " receive");
4523 vty_out (vty, "%s", VTY_NEWLINE);
4524 }
4525
4526 /* Route reflector client. */
4527 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4528 && ! peer->af_group[afi][safi])
4529 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4530 VTY_NEWLINE);
4531
4532 /* Nexthop self. */
4533 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4534 && ! peer->af_group[afi][safi])
4535 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4536
4537 /* Remove private AS. */
4538 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4539 && ! peer->af_group[afi][safi])
4540 vty_out (vty, " neighbor %s remove-private-AS%s",
4541 addr, VTY_NEWLINE);
4542
4543 /* send-community print. */
4544 if (! peer->af_group[afi][safi])
4545 {
4546 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4547 {
4548 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4549 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4550 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4551 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4552 vty_out (vty, " neighbor %s send-community extended%s",
4553 addr, VTY_NEWLINE);
4554 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4555 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4556 }
4557 else
4558 {
4559 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4560 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4561 vty_out (vty, " no neighbor %s send-community both%s",
4562 addr, VTY_NEWLINE);
4563 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4564 vty_out (vty, " no neighbor %s send-community extended%s",
4565 addr, VTY_NEWLINE);
4566 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4567 vty_out (vty, " no neighbor %s send-community%s",
4568 addr, VTY_NEWLINE);
4569 }
4570 }
4571
4572 /* Default information */
4573 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4574 && ! peer->af_group[afi][safi])
4575 {
4576 vty_out (vty, " neighbor %s default-originate", addr);
4577 if (peer->default_rmap[afi][safi].name)
4578 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4579 vty_out (vty, "%s", VTY_NEWLINE);
4580 }
4581
4582 /* Soft reconfiguration inbound. */
4583 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4584 if (! peer->af_group[afi][safi] ||
4585 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4586 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4587 VTY_NEWLINE);
4588
4589 /* maximum-prefix. */
4590 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4591 if (! peer->af_group[afi][safi]
4592 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004593 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004594 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4595 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004596 {
hasso0a486e52005-02-01 20:57:17 +00004597 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4598 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4599 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4600 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4601 vty_out (vty, " warning-only");
4602 if (peer->pmax_restart[afi][safi])
4603 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4604 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004605 }
paul718e3742002-12-13 20:15:29 +00004606
4607 /* Route server client. */
4608 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4609 && ! peer->af_group[afi][safi])
4610 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4611
4612 /* Allow AS in. */
4613 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4614 if (! peer_group_active (peer)
4615 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4616 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4617 {
4618 if (peer->allowas_in[afi][safi] == 3)
4619 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4620 else
4621 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4622 peer->allowas_in[afi][safi], VTY_NEWLINE);
4623 }
4624
4625 /* Filter. */
4626 bgp_config_write_filter (vty, peer, afi, safi);
4627
4628 /* atribute-unchanged. */
4629 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4630 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4631 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4632 && ! peer->af_group[afi][safi])
4633 {
4634 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4635 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4636 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4637 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4638 else
4639 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4640 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4641 " as-path" : "",
4642 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4643 " next-hop" : "",
4644 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4645 " med" : "", VTY_NEWLINE);
4646 }
4647}
4648
4649/* Display "address-family" configuration header. */
4650void
4651bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4652 int *write)
4653{
4654 if (*write)
4655 return;
4656
4657 if (afi == AFI_IP && safi == SAFI_UNICAST)
4658 return;
4659
4660 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4661
4662 if (afi == AFI_IP)
4663 {
4664 if (safi == SAFI_MULTICAST)
4665 vty_out (vty, "ipv4 multicast");
4666 else if (safi == SAFI_MPLS_VPN)
4667 vty_out (vty, "vpnv4 unicast");
4668 }
4669 else if (afi == AFI_IP6)
4670 vty_out (vty, "ipv6");
4671
4672 vty_out (vty, "%s", VTY_NEWLINE);
4673
4674 *write = 1;
4675}
4676
4677/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004678static int
paul718e3742002-12-13 20:15:29 +00004679bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4680 safi_t safi)
4681{
4682 int write = 0;
4683 struct peer *peer;
4684 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004685 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004686
4687 bgp_config_write_network (vty, bgp, afi, safi, &write);
4688
4689 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4690
paul1eb8ef22005-04-07 07:30:20 +00004691 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004692 {
4693 if (group->conf->afc[afi][safi])
4694 {
4695 bgp_config_write_family_header (vty, afi, safi, &write);
4696 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4697 }
4698 }
paul1eb8ef22005-04-07 07:30:20 +00004699 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004700 {
4701 if (peer->afc[afi][safi])
4702 {
4703 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4704 {
4705 bgp_config_write_family_header (vty, afi, safi, &write);
4706 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4707 }
4708 }
4709 }
4710 if (write)
4711 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4712
4713 return write;
4714}
4715
4716int
4717bgp_config_write (struct vty *vty)
4718{
4719 int write = 0;
4720 struct bgp *bgp;
4721 struct peer_group *group;
4722 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004723 struct listnode *node, *nnode;
4724 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004725
4726 /* BGP Multiple instance. */
4727 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4728 {
4729 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4730 write++;
4731 }
4732
4733 /* BGP Config type. */
4734 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4735 {
4736 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4737 write++;
4738 }
4739
4740 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004741 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004742 {
4743 if (write)
4744 vty_out (vty, "!%s", VTY_NEWLINE);
4745
4746 /* Router bgp ASN */
4747 vty_out (vty, "router bgp %d", bgp->as);
4748
4749 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4750 {
4751 if (bgp->name)
4752 vty_out (vty, " view %s", bgp->name);
4753 }
4754 vty_out (vty, "%s", VTY_NEWLINE);
4755
4756 /* No Synchronization */
4757 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4758 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4759
4760 /* BGP fast-external-failover. */
4761 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4762 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4763
4764 /* BGP router ID. */
4765 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4766 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4767 VTY_NEWLINE);
4768
paul848973c2003-08-13 00:32:49 +00004769 /* BGP log-neighbor-changes. */
4770 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4771 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4772
paul718e3742002-12-13 20:15:29 +00004773 /* BGP configuration. */
4774 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4775 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4776
4777 /* BGP default ipv4-unicast. */
4778 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4779 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4780
4781 /* BGP default local-preference. */
4782 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4783 vty_out (vty, " bgp default local-preference %d%s",
4784 bgp->default_local_pref, VTY_NEWLINE);
4785
4786 /* BGP client-to-client reflection. */
4787 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4788 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4789
4790 /* BGP cluster ID. */
4791 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4792 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4793 VTY_NEWLINE);
4794
hassoe0701b72004-05-20 09:19:34 +00004795 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004796 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004797 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4798 VTY_NEWLINE);
4799
4800 /* Confederation peer */
4801 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004802 {
hassoe0701b72004-05-20 09:19:34 +00004803 int i;
paul718e3742002-12-13 20:15:29 +00004804
hassoe0701b72004-05-20 09:19:34 +00004805 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004806
hassoe0701b72004-05-20 09:19:34 +00004807 for (i = 0; i < bgp->confed_peers_cnt; i++)
4808 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004809
hassoe0701b72004-05-20 09:19:34 +00004810 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004811 }
4812
4813 /* BGP enforce-first-as. */
4814 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4815 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4816
4817 /* BGP deterministic-med. */
4818 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4819 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004820
4821 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004822 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4823 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4824 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004825 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4826 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4827
paul718e3742002-12-13 20:15:29 +00004828 /* BGP bestpath method. */
4829 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4830 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004831 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4832 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004833 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4834 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4835 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4836 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4837 {
4838 vty_out (vty, " bgp bestpath med");
4839 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4840 vty_out (vty, " confed");
4841 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4842 vty_out (vty, " missing-as-worst");
4843 vty_out (vty, "%s", VTY_NEWLINE);
4844 }
4845
4846 /* BGP network import check. */
4847 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4848 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4849
4850 /* BGP scan interval. */
4851 bgp_config_write_scan_time (vty);
4852
4853 /* BGP flag dampening. */
4854 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4855 BGP_CONFIG_DAMPENING))
4856 bgp_config_write_damp (vty);
4857
4858 /* BGP static route configuration. */
4859 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4860
4861 /* BGP redistribute configuration. */
4862 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4863
4864 /* BGP timers configuration. */
4865 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4866 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4867 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4868 bgp->default_holdtime, VTY_NEWLINE);
4869
4870 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004871 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004872 {
4873 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4874 }
4875
4876 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004877 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004878 {
4879 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4880 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4881 }
4882
4883 /* Distance configuration. */
4884 bgp_config_write_distance (vty, bgp);
4885
4886 /* No auto-summary */
4887 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4888 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4889
4890 /* IPv4 multicast configuration. */
4891 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4892
4893 /* IPv4 VPN configuration. */
4894 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4895
4896 /* IPv6 unicast configuration. */
4897 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4898
4899 write++;
4900 }
4901 return write;
4902}
4903
4904void
paul94f2b392005-06-28 12:44:16 +00004905bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00004906{
4907 memset (&bgp_master, 0, sizeof (struct bgp_master));
4908
4909 bm = &bgp_master;
4910 bm->bgp = list_new ();
4911 bm->port = BGP_PORT_DEFAULT;
4912 bm->master = thread_master_create ();
4913 bm->start_time = time (NULL);
4914}
paul200df112005-06-01 11:17:05 +00004915
paul718e3742002-12-13 20:15:29 +00004916
4917void
paul94f2b392005-06-28 12:44:16 +00004918bgp_init (void)
paul718e3742002-12-13 20:15:29 +00004919{
paul718e3742002-12-13 20:15:29 +00004920 /* BGP VTY commands installation. */
4921 bgp_vty_init ();
4922
4923 /* Create BGP server socket. */
4924 bgp_socket (NULL, bm->port);
4925
4926 /* Init zebra. */
4927 bgp_zebra_init ();
4928
4929 /* BGP inits. */
4930 bgp_attr_init ();
4931 bgp_debug_init ();
4932 bgp_dump_init ();
4933 bgp_route_init ();
4934 bgp_route_map_init ();
4935 bgp_scan_init ();
4936 bgp_mplsvpn_init ();
4937
4938 /* Access list initialize. */
4939 access_list_init ();
4940 access_list_add_hook (peer_distribute_update);
4941 access_list_delete_hook (peer_distribute_update);
4942
4943 /* Filter list initialize. */
4944 bgp_filter_init ();
4945 as_list_add_hook (peer_aslist_update);
4946 as_list_delete_hook (peer_aslist_update);
4947
4948 /* Prefix list initialize.*/
4949 prefix_list_init ();
4950 prefix_list_add_hook (peer_prefix_list_update);
4951 prefix_list_delete_hook (peer_prefix_list_update);
4952
4953 /* Community list initialize. */
4954 bgp_clist = community_list_init ();
4955
4956#ifdef HAVE_SNMP
4957 bgp_snmp_init ();
4958#endif /* HAVE_SNMP */
4959}
paul545acaf2004-04-20 15:13:15 +00004960
4961void
4962bgp_terminate ()
4963{
paul545acaf2004-04-20 15:13:15 +00004964 struct bgp *bgp;
4965 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004966 struct listnode *node, *nnode;
4967 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004968
paul1eb8ef22005-04-07 07:30:20 +00004969 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4970 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00004971 if (peer->status == Established)
4972 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4973 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00004974
paul545acaf2004-04-20 15:13:15 +00004975 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00004976 if (bm->process_main_queue)
4977 work_queue_free (bm->process_main_queue);
4978 if (bm->process_rsclient_queue)
4979 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00004980}
4981