blob: e86fca342257c91f06f4f48a5beac46d701c93d6 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070060#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000061#ifdef HAVE_SNMP
62#include "bgpd/bgp_snmp.h"
63#endif /* HAVE_SNMP */
64
65/* BGP process wide configuration. */
66static struct bgp_master bgp_master;
67
hasso18a6dce2004-10-03 18:18:34 +000068extern struct in_addr router_id_zebra;
69
paul718e3742002-12-13 20:15:29 +000070/* BGP process wide configuration pointer to export. */
71struct bgp_master *bm;
72
73/* BGP community-list. */
74struct community_list_handler *bgp_clist;
75
76/* BGP global flag manipulation. */
77int
78bgp_option_set (int flag)
79{
80 switch (flag)
81 {
82 case BGP_OPT_NO_FIB:
83 case BGP_OPT_MULTIPLE_INSTANCE:
84 case BGP_OPT_CONFIG_CISCO:
85 SET_FLAG (bm->options, flag);
86 break;
87 default:
88 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000089 }
90 return 0;
91}
92
93int
94bgp_option_unset (int flag)
95{
96 switch (flag)
97 {
98 case BGP_OPT_MULTIPLE_INSTANCE:
99 if (listcount (bm->bgp) > 1)
100 return BGP_ERR_MULTIPLE_INSTANCE_USED;
101 /* Fall through. */
102 case BGP_OPT_NO_FIB:
103 case BGP_OPT_CONFIG_CISCO:
104 UNSET_FLAG (bm->options, flag);
105 break;
106 default:
107 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000108 }
109 return 0;
110}
111
112int
113bgp_option_check (int flag)
114{
115 return CHECK_FLAG (bm->options, flag);
116}
117
118/* BGP flag manipulation. */
119int
120bgp_flag_set (struct bgp *bgp, int flag)
121{
122 SET_FLAG (bgp->flags, flag);
123 return 0;
124}
125
126int
127bgp_flag_unset (struct bgp *bgp, int flag)
128{
129 UNSET_FLAG (bgp->flags, flag);
130 return 0;
131}
132
133int
134bgp_flag_check (struct bgp *bgp, int flag)
135{
136 return CHECK_FLAG (bgp->flags, flag);
137}
138
139/* Internal function to set BGP structure configureation flag. */
140static void
141bgp_config_set (struct bgp *bgp, int config)
142{
143 SET_FLAG (bgp->config, config);
144}
145
146static void
147bgp_config_unset (struct bgp *bgp, int config)
148{
149 UNSET_FLAG (bgp->config, config);
150}
151
152static int
153bgp_config_check (struct bgp *bgp, int config)
154{
155 return CHECK_FLAG (bgp->config, config);
156}
157
158/* Set BGP router identifier. */
159int
160bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
161{
162 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000163 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000164
165 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
166 && IPV4_ADDR_SAME (&bgp->router_id, id))
167 return 0;
168
169 IPV4_ADDR_COPY (&bgp->router_id, id);
170 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
171
172 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000174 {
175 IPV4_ADDR_COPY (&peer->local_id, id);
176
177 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000178 {
179 peer->last_reset = PEER_DOWN_RID_CHANGE;
180 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
181 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
182 }
paul718e3742002-12-13 20:15:29 +0000183 }
184 return 0;
185}
186
paul718e3742002-12-13 20:15:29 +0000187/* BGP's cluster-id control. */
188int
189bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
190{
191 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000192 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000193
194 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
195 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
196 return 0;
197
198 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
199 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
200
201 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000202 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000203 {
204 if (peer_sort (peer) != BGP_PEER_IBGP)
205 continue;
206
207 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000208 {
209 peer->last_reset = PEER_DOWN_CLID_CHANGE;
210 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
211 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
212 }
paul718e3742002-12-13 20:15:29 +0000213 }
214 return 0;
215}
216
217int
218bgp_cluster_id_unset (struct bgp *bgp)
219{
220 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000221 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000222
223 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
224 return 0;
225
226 bgp->cluster_id.s_addr = 0;
227 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
228
229 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000230 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000231 {
232 if (peer_sort (peer) != BGP_PEER_IBGP)
233 continue;
234
235 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000236 {
237 peer->last_reset = PEER_DOWN_CLID_CHANGE;
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
239 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
240 }
paul718e3742002-12-13 20:15:29 +0000241 }
242 return 0;
243}
244
Stephen Hemminger65957882010-01-15 16:22:10 +0300245/* time_t value that is monotonicly increasing
246 * and uneffected by adjustments to system clock
247 */
248time_t bgp_clock (void)
249{
250 struct timeval tv;
251
252 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
253 return tv.tv_sec;
254}
255
paul718e3742002-12-13 20:15:29 +0000256/* BGP timer configuration. */
257int
258bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
259{
260 bgp->default_keepalive = (keepalive < holdtime / 3
261 ? keepalive : holdtime / 3);
262 bgp->default_holdtime = holdtime;
263
264 return 0;
265}
266
267int
268bgp_timers_unset (struct bgp *bgp)
269{
270 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
271 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
272
273 return 0;
274}
275
276/* BGP confederation configuration. */
277int
278bgp_confederation_id_set (struct bgp *bgp, as_t as)
279{
280 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000281 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000282 int already_confed;
283
284 if (as == 0)
285 return BGP_ERR_INVALID_AS;
286
287 /* Remember - were we doing confederation before? */
288 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
289 bgp->confed_id = as;
290 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
291
292 /* If we were doing confederation already, this is just an external
293 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
294 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000295 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000296 {
297 /* We're looking for peers who's AS is not local or part of our
298 confederation. */
299 if (already_confed)
300 {
301 if (peer_sort (peer) == BGP_PEER_EBGP)
302 {
303 peer->local_as = as;
304 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000305 {
306 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
307 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
308 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
309 }
310
paul718e3742002-12-13 20:15:29 +0000311 else
312 BGP_EVENT_ADD (peer, BGP_Stop);
313 }
314 }
315 else
316 {
317 /* Not doign confederation before, so reset every non-local
318 session */
319 if (peer_sort (peer) != BGP_PEER_IBGP)
320 {
321 /* Reset the local_as to be our EBGP one */
322 if (peer_sort (peer) == BGP_PEER_EBGP)
323 peer->local_as = as;
324 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000325 {
326 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
327 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
328 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
329 }
paul718e3742002-12-13 20:15:29 +0000330 else
331 BGP_EVENT_ADD (peer, BGP_Stop);
332 }
333 }
334 }
335 return 0;
336}
337
338int
339bgp_confederation_id_unset (struct bgp *bgp)
340{
341 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000342 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000343
344 bgp->confed_id = 0;
345 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
346
paul1eb8ef22005-04-07 07:30:20 +0000347 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000348 {
349 /* We're looking for peers who's AS is not local */
350 if (peer_sort (peer) != BGP_PEER_IBGP)
351 {
352 peer->local_as = bgp->as;
353 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000354 {
355 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
356 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
357 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
358 }
359
paul718e3742002-12-13 20:15:29 +0000360 else
361 BGP_EVENT_ADD (peer, BGP_Stop);
362 }
363 }
364 return 0;
365}
366
367/* Is an AS part of the confed or not? */
368int
369bgp_confederation_peers_check (struct bgp *bgp, as_t as)
370{
371 int i;
372
373 if (! bgp)
374 return 0;
375
376 for (i = 0; i < bgp->confed_peers_cnt; i++)
377 if (bgp->confed_peers[i] == as)
378 return 1;
379
380 return 0;
381}
382
383/* Add an AS to the confederation set. */
384int
385bgp_confederation_peers_add (struct bgp *bgp, as_t as)
386{
387 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000389
390 if (! bgp)
391 return BGP_ERR_INVALID_BGP;
392
393 if (bgp->as == as)
394 return BGP_ERR_INVALID_AS;
395
396 if (bgp_confederation_peers_check (bgp, as))
397 return -1;
398
399 if (bgp->confed_peers)
400 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
401 bgp->confed_peers,
402 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
403 else
404 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
405 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
406
407 bgp->confed_peers[bgp->confed_peers_cnt] = as;
408 bgp->confed_peers_cnt++;
409
410 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
411 {
paul1eb8ef22005-04-07 07:30:20 +0000412 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000413 {
414 if (peer->as == as)
415 {
416 peer->local_as = bgp->as;
417 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000418 {
419 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
420 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
421 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
422 }
paul718e3742002-12-13 20:15:29 +0000423 else
424 BGP_EVENT_ADD (peer, BGP_Stop);
425 }
426 }
427 }
428 return 0;
429}
430
431/* Delete an AS from the confederation set. */
432int
433bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
434{
435 int i;
436 int j;
437 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000438 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000439
440 if (! bgp)
441 return -1;
442
443 if (! bgp_confederation_peers_check (bgp, as))
444 return -1;
445
446 for (i = 0; i < bgp->confed_peers_cnt; i++)
447 if (bgp->confed_peers[i] == as)
448 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
449 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
450
451 bgp->confed_peers_cnt--;
452
453 if (bgp->confed_peers_cnt == 0)
454 {
455 if (bgp->confed_peers)
456 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
457 bgp->confed_peers = NULL;
458 }
459 else
460 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
461 bgp->confed_peers,
462 bgp->confed_peers_cnt * sizeof (as_t));
463
464 /* Now reset any peer who's remote AS has just been removed from the
465 CONFED */
466 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
467 {
paul1eb8ef22005-04-07 07:30:20 +0000468 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000469 {
470 if (peer->as == as)
471 {
472 peer->local_as = bgp->confed_id;
473 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000474 {
475 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
476 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
477 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
478 }
paul718e3742002-12-13 20:15:29 +0000479 else
480 BGP_EVENT_ADD (peer, BGP_Stop);
481 }
482 }
483 }
484
485 return 0;
486}
487
488/* Local preference configuration. */
489int
490bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
491{
492 if (! bgp)
493 return -1;
494
paul718e3742002-12-13 20:15:29 +0000495 bgp->default_local_pref = local_pref;
496
497 return 0;
498}
499
500int
501bgp_default_local_preference_unset (struct bgp *bgp)
502{
503 if (! bgp)
504 return -1;
505
paul718e3742002-12-13 20:15:29 +0000506 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
507
508 return 0;
509}
510
paulfee0f4c2004-09-13 05:12:46 +0000511/* If peer is RSERVER_CLIENT in at least one address family and is not member
512 of a peer_group for that family, return 1.
513 Used to check wether the peer is included in list bgp->rsclient. */
514int
515peer_rsclient_active (struct peer *peer)
516{
517 int i;
518 int j;
519
520 for (i=AFI_IP; i < AFI_MAX; i++)
521 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
522 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
523 && ! peer->af_group[i][j])
524 return 1;
525 return 0;
526}
527
pauleb821182004-05-01 08:44:08 +0000528/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000529static int
530peer_cmp (struct peer *p1, struct peer *p2)
531{
pauleb821182004-05-01 08:44:08 +0000532 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000533}
534
535int
536peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
537{
538 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
539}
540
541/* Reset all address family specific configuration. */
542static void
543peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
544{
545 int i;
546 struct bgp_filter *filter;
547 char orf_name[BUFSIZ];
548
549 filter = &peer->filter[afi][safi];
550
551 /* Clear neighbor filter and route-map */
552 for (i = FILTER_IN; i < FILTER_MAX; i++)
553 {
554 if (filter->dlist[i].name)
555 {
556 free (filter->dlist[i].name);
557 filter->dlist[i].name = NULL;
558 }
559 if (filter->plist[i].name)
560 {
561 free (filter->plist[i].name);
562 filter->plist[i].name = NULL;
563 }
564 if (filter->aslist[i].name)
565 {
566 free (filter->aslist[i].name);
567 filter->aslist[i].name = NULL;
568 }
paulfee0f4c2004-09-13 05:12:46 +0000569 }
570 for (i = RMAP_IN; i < RMAP_MAX; i++)
571 {
paul718e3742002-12-13 20:15:29 +0000572 if (filter->map[i].name)
573 {
574 free (filter->map[i].name);
575 filter->map[i].name = NULL;
576 }
577 }
578
579 /* Clear unsuppress map. */
580 if (filter->usmap.name)
581 free (filter->usmap.name);
582 filter->usmap.name = NULL;
583 filter->usmap.map = NULL;
584
585 /* Clear neighbor's all address family flags. */
586 peer->af_flags[afi][safi] = 0;
587
588 /* Clear neighbor's all address family sflags. */
589 peer->af_sflags[afi][safi] = 0;
590
591 /* Clear neighbor's all address family capabilities. */
592 peer->af_cap[afi][safi] = 0;
593
594 /* Clear ORF info */
595 peer->orf_plist[afi][safi] = NULL;
596 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
597 prefix_bgp_orf_remove_all (orf_name);
598
599 /* Set default neighbor send-community. */
600 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
601 {
602 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
604 }
605
606 /* Clear neighbor default_originate_rmap */
607 if (peer->default_rmap[afi][safi].name)
608 free (peer->default_rmap[afi][safi].name);
609 peer->default_rmap[afi][safi].name = NULL;
610 peer->default_rmap[afi][safi].map = NULL;
611
612 /* Clear neighbor maximum-prefix */
613 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000614 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000615}
616
617/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000618static void
paul718e3742002-12-13 20:15:29 +0000619peer_global_config_reset (struct peer *peer)
620{
621 peer->weight = 0;
622 peer->change_local_as = 0;
623 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
624 if (peer->update_source)
625 {
626 sockunion_free (peer->update_source);
627 peer->update_source = NULL;
628 }
629 if (peer->update_if)
630 {
631 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
632 peer->update_if = NULL;
633 }
634
635 if (peer_sort (peer) == BGP_PEER_IBGP)
636 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
637 else
638 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
639
640 peer->flags = 0;
641 peer->config = 0;
642 peer->holdtime = 0;
643 peer->keepalive = 0;
644 peer->connect = 0;
645 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
646}
647
648/* Check peer's AS number and determin is this peer IBGP or EBGP */
649int
650peer_sort (struct peer *peer)
651{
652 struct bgp *bgp;
653
654 bgp = peer->bgp;
655
656 /* Peer-group */
657 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
658 {
659 if (peer->as)
660 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
661 else
662 {
663 struct peer *peer1;
664 peer1 = listnode_head (peer->group->peer);
665 if (peer1)
666 return (peer1->local_as == peer1->as
667 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
668 }
669 return BGP_PEER_INTERNAL;
670 }
671
672 /* Normal peer */
673 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
674 {
675 if (peer->local_as == 0)
676 return BGP_PEER_INTERNAL;
677
678 if (peer->local_as == peer->as)
679 {
680 if (peer->local_as == bgp->confed_id)
681 return BGP_PEER_EBGP;
682 else
683 return BGP_PEER_IBGP;
684 }
685
686 if (bgp_confederation_peers_check (bgp, peer->as))
687 return BGP_PEER_CONFED;
688
689 return BGP_PEER_EBGP;
690 }
691 else
692 {
693 return (peer->local_as == 0
694 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
695 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
696 }
697}
698
paul200df112005-06-01 11:17:05 +0000699static inline void
700peer_free (struct peer *peer)
701{
Paul Jakmaca058a32006-09-14 02:58:49 +0000702 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700703
704 bgp_unlock(peer->bgp);
705
Paul Jakmaca058a32006-09-14 02:58:49 +0000706 /* this /ought/ to have been done already through bgp_stop earlier,
707 * but just to be sure..
708 */
709 bgp_timer_set (peer);
710 BGP_READ_OFF (peer->t_read);
711 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000712 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000713
paul200df112005-06-01 11:17:05 +0000714 if (peer->desc)
715 XFREE (MTYPE_PEER_DESC, peer->desc);
716
717 /* Free allocated host character. */
718 if (peer->host)
719 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
720
721 /* Update source configuration. */
722 if (peer->update_source)
723 sockunion_free (peer->update_source);
724
725 if (peer->update_if)
726 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000727
728 if (peer->clear_node_queue)
729 work_queue_free (peer->clear_node_queue);
730
Paul Jakmaca058a32006-09-14 02:58:49 +0000731 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000732 memset (peer, 0, sizeof (struct peer));
733
734 XFREE (MTYPE_BGP_PEER, peer);
735}
736
737/* increase reference count on a struct peer */
738struct peer *
739peer_lock (struct peer *peer)
740{
741 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000742
paul200df112005-06-01 11:17:05 +0000743 peer->lock++;
744
745 return peer;
746}
747
748/* decrease reference count on a struct peer
749 * struct peer is freed and NULL returned if last reference
750 */
751struct peer *
752peer_unlock (struct peer *peer)
753{
754 assert (peer && (peer->lock > 0));
755
756 peer->lock--;
757
758 if (peer->lock == 0)
759 {
760#if 0
761 zlog_debug ("unlocked and freeing");
762 zlog_backtrace (LOG_DEBUG);
763#endif
764 peer_free (peer);
765 return NULL;
766 }
767
768#if 0
769 if (peer->lock == 1)
770 {
771 zlog_debug ("unlocked to 1");
772 zlog_backtrace (LOG_DEBUG);
773 }
774#endif
775
776 return peer;
777}
778
779/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000780static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000781peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000782{
783 afi_t afi;
784 safi_t safi;
785 struct peer *peer;
786 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000787
788 /* bgp argument is absolutely required */
789 assert (bgp);
790 if (!bgp)
791 return NULL;
792
paul718e3742002-12-13 20:15:29 +0000793 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000794 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000795
796 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000797 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000798 peer->v_start = BGP_INIT_START_TIMER;
799 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
800 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
801 peer->status = Idle;
802 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000803 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000804 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000805 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000806 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700807 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000808
809 /* Set default flags. */
810 for (afi = AFI_IP; afi < AFI_MAX; afi++)
811 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
812 {
813 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
814 {
815 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
816 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
817 }
818 peer->orf_plist[afi][safi] = NULL;
819 }
820 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
821
822 /* Create buffers. */
823 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
824 peer->obuf = stream_fifo_new ();
825 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
826
827 bgp_sync_init (peer);
828
829 /* Get service port number. */
830 sp = getservbyname ("bgp", "tcp");
831 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
832
833 return peer;
834}
835
836/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000837static struct peer *
paul718e3742002-12-13 20:15:29 +0000838peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
839 as_t remote_as, afi_t afi, safi_t safi)
840{
841 int active;
842 struct peer *peer;
843 char buf[SU_ADDRSTRLEN];
844
Paul Jakma6f585442006-10-22 19:13:07 +0000845 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000846 peer->su = *su;
847 peer->local_as = local_as;
848 peer->as = remote_as;
849 peer->local_id = bgp->router_id;
850 peer->v_holdtime = bgp->default_holdtime;
851 peer->v_keepalive = bgp->default_keepalive;
852 if (peer_sort (peer) == BGP_PEER_IBGP)
853 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
854 else
855 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000856
857 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000858 listnode_add_sort (bgp->peer, peer);
859
860 active = peer_active (peer);
861
862 if (afi && safi)
863 peer->afc[afi][safi] = 1;
864
Stephen Hemminger65957882010-01-15 16:22:10 +0300865 /* Last read and reset time set */
866 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000867
paul718e3742002-12-13 20:15:29 +0000868 /* Default TTL set. */
869 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
870
871 /* Make peer's address string. */
872 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000873 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000874
875 /* Set up peer's events and timers. */
876 if (! active && peer_active (peer))
877 bgp_timer_set (peer);
878
879 return peer;
880}
881
pauleb821182004-05-01 08:44:08 +0000882/* Make accept BGP peer. Called from bgp_accept (). */
883struct peer *
884peer_create_accept (struct bgp *bgp)
885{
886 struct peer *peer;
887
Paul Jakma6f585442006-10-22 19:13:07 +0000888 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000889
890 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000891 listnode_add_sort (bgp->peer, peer);
892
893 return peer;
894}
895
paul718e3742002-12-13 20:15:29 +0000896/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000897static void
paul718e3742002-12-13 20:15:29 +0000898peer_as_change (struct peer *peer, as_t as)
899{
900 int type;
901
902 /* Stop peer. */
903 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
904 {
905 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000906 {
907 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
908 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
909 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
910 }
paul718e3742002-12-13 20:15:29 +0000911 else
912 BGP_EVENT_ADD (peer, BGP_Stop);
913 }
914 type = peer_sort (peer);
915 peer->as = as;
916
paul848973c2003-08-13 00:32:49 +0000917 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
918 && ! bgp_confederation_peers_check (peer->bgp, as)
919 && peer->bgp->as != as)
920 peer->local_as = peer->bgp->confed_id;
921 else
922 peer->local_as = peer->bgp->as;
923
paul718e3742002-12-13 20:15:29 +0000924 /* Advertisement-interval reset */
925 if (peer_sort (peer) == BGP_PEER_IBGP)
926 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
927 else
928 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
929
930 /* TTL reset */
931 if (peer_sort (peer) == BGP_PEER_IBGP)
932 peer->ttl = 255;
933 else if (type == BGP_PEER_IBGP)
934 peer->ttl = 1;
935
936 /* reflector-client reset */
937 if (peer_sort (peer) != BGP_PEER_IBGP)
938 {
939 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
940 PEER_FLAG_REFLECTOR_CLIENT);
941 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
942 PEER_FLAG_REFLECTOR_CLIENT);
943 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
944 PEER_FLAG_REFLECTOR_CLIENT);
945 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
946 PEER_FLAG_REFLECTOR_CLIENT);
947 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
948 PEER_FLAG_REFLECTOR_CLIENT);
949 }
950
951 /* local-as reset */
952 if (peer_sort (peer) != BGP_PEER_EBGP)
953 {
954 peer->change_local_as = 0;
955 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
956 }
957}
958
959/* If peer does not exist, create new one. If peer already exists,
960 set AS number to the peer. */
961int
962peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
963 afi_t afi, safi_t safi)
964{
965 struct peer *peer;
966 as_t local_as;
967
968 peer = peer_lookup (bgp, su);
969
970 if (peer)
971 {
972 /* When this peer is a member of peer-group. */
973 if (peer->group)
974 {
975 if (peer->group->conf->as)
976 {
977 /* Return peer group's AS number. */
978 *as = peer->group->conf->as;
979 return BGP_ERR_PEER_GROUP_MEMBER;
980 }
981 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
982 {
983 if (bgp->as != *as)
984 {
985 *as = peer->as;
986 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
987 }
988 }
989 else
990 {
991 if (bgp->as == *as)
992 {
993 *as = peer->as;
994 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
995 }
996 }
997 }
998
999 /* Existing peer's AS number change. */
1000 if (peer->as != *as)
1001 peer_as_change (peer, *as);
1002 }
1003 else
1004 {
1005
1006 /* If the peer is not part of our confederation, and its not an
1007 iBGP peer then spoof the source AS */
1008 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1009 && ! bgp_confederation_peers_check (bgp, *as)
1010 && bgp->as != *as)
1011 local_as = bgp->confed_id;
1012 else
1013 local_as = bgp->as;
1014
1015 /* If this is IPv4 unicast configuration and "no bgp default
1016 ipv4-unicast" is specified. */
1017
1018 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1019 && afi == AFI_IP && safi == SAFI_UNICAST)
1020 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1021 else
1022 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1023 }
1024
1025 return 0;
1026}
1027
1028/* Activate the peer or peer group for specified AFI and SAFI. */
1029int
1030peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1031{
1032 int active;
1033
1034 if (peer->afc[afi][safi])
1035 return 0;
1036
1037 /* Activate the address family configuration. */
1038 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1039 peer->afc[afi][safi] = 1;
1040 else
1041 {
1042 active = peer_active (peer);
1043
1044 peer->afc[afi][safi] = 1;
1045
1046 if (! active && peer_active (peer))
1047 bgp_timer_set (peer);
1048 else
1049 {
1050 if (peer->status == Established)
1051 {
1052 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1053 {
1054 peer->afc_adv[afi][safi] = 1;
1055 bgp_capability_send (peer, afi, safi,
1056 CAPABILITY_CODE_MP,
1057 CAPABILITY_ACTION_SET);
1058 if (peer->afc_recv[afi][safi])
1059 {
1060 peer->afc_nego[afi][safi] = 1;
1061 bgp_announce_route (peer, afi, safi);
1062 }
1063 }
1064 else
hassoe0701b72004-05-20 09:19:34 +00001065 {
1066 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1067 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1068 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1069 }
paul718e3742002-12-13 20:15:29 +00001070 }
1071 }
1072 }
1073 return 0;
1074}
1075
1076int
1077peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1078{
1079 struct peer_group *group;
1080 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001081 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001082
1083 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1084 {
1085 group = peer->group;
1086
paul1eb8ef22005-04-07 07:30:20 +00001087 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001088 {
1089 if (peer1->af_group[afi][safi])
1090 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1091 }
1092 }
1093 else
1094 {
1095 if (peer->af_group[afi][safi])
1096 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1097 }
1098
1099 if (! peer->afc[afi][safi])
1100 return 0;
1101
1102 /* De-activate the address family configuration. */
1103 peer->afc[afi][safi] = 0;
1104 peer_af_flag_reset (peer, afi, safi);
1105
1106 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1107 {
1108 if (peer->status == Established)
1109 {
1110 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1111 {
1112 peer->afc_adv[afi][safi] = 0;
1113 peer->afc_nego[afi][safi] = 0;
1114
1115 if (peer_active_nego (peer))
1116 {
1117 bgp_capability_send (peer, afi, safi,
1118 CAPABILITY_CODE_MP,
1119 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001120 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001121 peer->pcount[afi][safi] = 0;
1122 }
1123 else
hassoe0701b72004-05-20 09:19:34 +00001124 {
1125 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1126 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1127 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1128 }
paul718e3742002-12-13 20:15:29 +00001129 }
1130 else
hassoe0701b72004-05-20 09:19:34 +00001131 {
1132 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1133 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1134 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1135 }
paul718e3742002-12-13 20:15:29 +00001136 }
1137 }
1138 return 0;
1139}
1140
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001141static void
hasso93406d82005-02-02 14:40:33 +00001142peer_nsf_stop (struct peer *peer)
1143{
1144 afi_t afi;
1145 safi_t safi;
1146
1147 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1148 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1149
1150 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1151 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1152 peer->nsf[afi][safi] = 0;
1153
1154 if (peer->t_gr_restart)
1155 {
1156 BGP_TIMER_OFF (peer->t_gr_restart);
1157 if (BGP_DEBUG (events, EVENTS))
1158 zlog_debug ("%s graceful restart timer stopped", peer->host);
1159 }
1160 if (peer->t_gr_stale)
1161 {
1162 BGP_TIMER_OFF (peer->t_gr_stale);
1163 if (BGP_DEBUG (events, EVENTS))
1164 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1165 }
1166 bgp_clear_route_all (peer);
1167}
1168
Paul Jakmaca058a32006-09-14 02:58:49 +00001169/* Delete peer from confguration.
1170 *
1171 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1172 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1173 *
1174 * This function /should/ take care to be idempotent, to guard against
1175 * it being called multiple times through stray events that come in
1176 * that happen to result in this function being called again. That
1177 * said, getting here for a "Deleted" peer is a bug in the neighbour
1178 * FSM.
1179 */
paul718e3742002-12-13 20:15:29 +00001180int
1181peer_delete (struct peer *peer)
1182{
1183 int i;
1184 afi_t afi;
1185 safi_t safi;
1186 struct bgp *bgp;
1187 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001188 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001189
Paul Jakmaca058a32006-09-14 02:58:49 +00001190 assert (peer->status != Deleted);
1191
paul718e3742002-12-13 20:15:29 +00001192 bgp = peer->bgp;
1193
hasso93406d82005-02-02 14:40:33 +00001194 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1195 peer_nsf_stop (peer);
1196
Chris Caputo228da422009-07-18 05:44:03 +00001197 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001198 relationship. */
1199 if (peer->group)
1200 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001201 if ((pn = listnode_lookup (peer->group->peer, peer)))
1202 {
1203 peer = peer_unlock (peer); /* group->peer list reference */
1204 list_delete_node (peer->group->peer, pn);
1205 }
paul718e3742002-12-13 20:15:29 +00001206 peer->group = NULL;
1207 }
paul200df112005-06-01 11:17:05 +00001208
paul718e3742002-12-13 20:15:29 +00001209 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001210 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1211 * executed after peer structure is deleted.
1212 */
hassoe0701b72004-05-20 09:19:34 +00001213 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001214 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001215 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001216
1217 /* Password configuration */
1218 if (peer->password)
1219 {
1220 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1221 peer->password = NULL;
1222
1223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1224 bgp_md5_set (peer);
1225 }
1226
Paul Jakmaca058a32006-09-14 02:58:49 +00001227 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001228
paul718e3742002-12-13 20:15:29 +00001229 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001230 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1231 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001232 {
Chris Caputo228da422009-07-18 05:44:03 +00001233 peer_unlock (peer); /* bgp peer list reference */
1234 list_delete_node (bgp->peer, pn);
1235 }
paul200df112005-06-01 11:17:05 +00001236
Chris Caputo228da422009-07-18 05:44:03 +00001237 if (peer_rsclient_active (peer)
1238 && (pn = listnode_lookup (bgp->rsclient, peer)))
1239 {
1240 peer_unlock (peer); /* rsclient list reference */
1241 list_delete_node (bgp->rsclient, pn);
1242
1243 /* Clear our own rsclient ribs. */
1244 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1245 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1246 if (CHECK_FLAG(peer->af_flags[afi][safi],
1247 PEER_FLAG_RSERVER_CLIENT))
1248 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001249 }
1250
1251 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1252 member of a peer_group. */
1253 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1254 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1255 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001256 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001257
paul200df112005-06-01 11:17:05 +00001258 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001259 if (peer->ibuf)
1260 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001261 if (peer->obuf)
1262 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001263 if (peer->work)
1264 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001265 peer->obuf = NULL;
1266 peer->work = peer->ibuf = NULL;
1267
paul718e3742002-12-13 20:15:29 +00001268 /* Local and remote addresses. */
1269 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001270 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001271 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001272 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001273 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001274
paul718e3742002-12-13 20:15:29 +00001275 /* Free filter related memory. */
1276 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1277 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1278 {
1279 filter = &peer->filter[afi][safi];
1280
1281 for (i = FILTER_IN; i < FILTER_MAX; i++)
1282 {
1283 if (filter->dlist[i].name)
1284 free (filter->dlist[i].name);
1285 if (filter->plist[i].name)
1286 free (filter->plist[i].name);
1287 if (filter->aslist[i].name)
1288 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001289
1290 filter->dlist[i].name = NULL;
1291 filter->plist[i].name = NULL;
1292 filter->aslist[i].name = NULL;
1293 }
1294 for (i = RMAP_IN; i < RMAP_MAX; i++)
1295 {
paul718e3742002-12-13 20:15:29 +00001296 if (filter->map[i].name)
1297 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001298 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001299 }
1300
1301 if (filter->usmap.name)
1302 free (filter->usmap.name);
1303
1304 if (peer->default_rmap[afi][safi].name)
1305 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001306
1307 filter->usmap.name = NULL;
1308 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001309 }
paul200df112005-06-01 11:17:05 +00001310
1311 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001312
1313 return 0;
1314}
1315
paul94f2b392005-06-28 12:44:16 +00001316static int
paul718e3742002-12-13 20:15:29 +00001317peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1318{
1319 return strcmp (g1->name, g2->name);
1320}
1321
1322/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001323static int
paul718e3742002-12-13 20:15:29 +00001324peer_group_active (struct peer *peer)
1325{
1326 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1327 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1328 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1329 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1330 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1331 return 1;
1332 return 0;
1333}
1334
1335/* Peer group cofiguration. */
1336static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001337peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001338{
1339 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1340 sizeof (struct peer_group));
1341}
1342
paul94f2b392005-06-28 12:44:16 +00001343static void
paul718e3742002-12-13 20:15:29 +00001344peer_group_free (struct peer_group *group)
1345{
1346 XFREE (MTYPE_PEER_GROUP, group);
1347}
1348
1349struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001350peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001351{
1352 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001353 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001354
paul1eb8ef22005-04-07 07:30:20 +00001355 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001356 {
1357 if (strcmp (group->name, name) == 0)
1358 return group;
1359 }
1360 return NULL;
1361}
1362
1363struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001364peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001365{
1366 struct peer_group *group;
1367
1368 group = peer_group_lookup (bgp, name);
1369 if (group)
1370 return group;
1371
1372 group = peer_group_new ();
1373 group->bgp = bgp;
1374 group->name = strdup (name);
1375 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001376 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001377 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1378 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001379 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001380 group->conf->group = group;
1381 group->conf->as = 0;
1382 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001383 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001384 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1385 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1386 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1387 group->conf->keepalive = 0;
1388 group->conf->holdtime = 0;
1389 group->conf->connect = 0;
1390 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1391 listnode_add_sort (bgp->group, group);
1392
1393 return 0;
1394}
1395
paul94f2b392005-06-28 12:44:16 +00001396static void
paul718e3742002-12-13 20:15:29 +00001397peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1398 afi_t afi, safi_t safi)
1399{
1400 int in = FILTER_IN;
1401 int out = FILTER_OUT;
1402 struct peer *conf;
1403 struct bgp_filter *pfilter;
1404 struct bgp_filter *gfilter;
1405
1406 conf = group->conf;
1407 pfilter = &peer->filter[afi][safi];
1408 gfilter = &conf->filter[afi][safi];
1409
1410 /* remote-as */
1411 if (conf->as)
1412 peer->as = conf->as;
1413
1414 /* remote-as */
1415 if (conf->change_local_as)
1416 peer->change_local_as = conf->change_local_as;
1417
1418 /* TTL */
1419 peer->ttl = conf->ttl;
1420
Nick Hilliardfa411a22011-03-23 15:33:17 +00001421 /* GTSM hops */
1422 peer->gtsm_hops = conf->gtsm_hops;
1423
paul718e3742002-12-13 20:15:29 +00001424 /* Weight */
1425 peer->weight = conf->weight;
1426
1427 /* peer flags apply */
1428 peer->flags = conf->flags;
1429 /* peer af_flags apply */
1430 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1431 /* peer config apply */
1432 peer->config = conf->config;
1433
1434 /* peer timers apply */
1435 peer->holdtime = conf->holdtime;
1436 peer->keepalive = conf->keepalive;
1437 peer->connect = conf->connect;
1438 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1439 peer->v_connect = conf->connect;
1440 else
1441 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1442
1443 /* advertisement-interval reset */
1444 if (peer_sort (peer) == BGP_PEER_IBGP)
1445 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1446 else
1447 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1448
Paul Jakma0df7c912008-07-21 21:02:49 +00001449 /* password apply */
1450 if (peer->password)
1451 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1452
1453 if (conf->password)
1454 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1455 else
1456 peer->password = NULL;
1457
1458 bgp_md5_set (peer);
1459
paul718e3742002-12-13 20:15:29 +00001460 /* maximum-prefix */
1461 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001462 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001463 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001464
1465 /* allowas-in */
1466 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1467
paulfee0f4c2004-09-13 05:12:46 +00001468 /* route-server-client */
1469 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1470 {
1471 /* Make peer's RIB point to group's RIB. */
1472 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1473
1474 /* Import policy. */
1475 if (pfilter->map[RMAP_IMPORT].name)
1476 free (pfilter->map[RMAP_IMPORT].name);
1477 if (gfilter->map[RMAP_IMPORT].name)
1478 {
1479 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1480 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1481 }
1482 else
1483 {
1484 pfilter->map[RMAP_IMPORT].name = NULL;
1485 pfilter->map[RMAP_IMPORT].map = NULL;
1486 }
1487
1488 /* Export policy. */
1489 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1490 {
1491 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1492 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1493 }
1494 }
1495
paul718e3742002-12-13 20:15:29 +00001496 /* default-originate route-map */
1497 if (conf->default_rmap[afi][safi].name)
1498 {
1499 if (peer->default_rmap[afi][safi].name)
1500 free (peer->default_rmap[afi][safi].name);
1501 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1502 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1503 }
1504
1505 /* update-source apply */
1506 if (conf->update_source)
1507 {
1508 if (peer->update_source)
1509 sockunion_free (peer->update_source);
1510 if (peer->update_if)
1511 {
1512 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1513 peer->update_if = NULL;
1514 }
1515 peer->update_source = sockunion_dup (conf->update_source);
1516 }
1517 else if (conf->update_if)
1518 {
1519 if (peer->update_if)
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 if (peer->update_source)
1522 {
1523 sockunion_free (peer->update_source);
1524 peer->update_source = NULL;
1525 }
1526 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1527 }
1528
1529 /* inbound filter apply */
1530 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1531 {
1532 if (pfilter->dlist[in].name)
1533 free (pfilter->dlist[in].name);
1534 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1535 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1536 }
1537 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1538 {
1539 if (pfilter->plist[in].name)
1540 free (pfilter->plist[in].name);
1541 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1542 pfilter->plist[in].plist = gfilter->plist[in].plist;
1543 }
1544 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1545 {
1546 if (pfilter->aslist[in].name)
1547 free (pfilter->aslist[in].name);
1548 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1549 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1550 }
paulfee0f4c2004-09-13 05:12:46 +00001551 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001552 {
paulfee0f4c2004-09-13 05:12:46 +00001553 if (pfilter->map[RMAP_IN].name)
1554 free (pfilter->map[RMAP_IN].name);
1555 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1556 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001557 }
1558
1559 /* outbound filter apply */
1560 if (gfilter->dlist[out].name)
1561 {
1562 if (pfilter->dlist[out].name)
1563 free (pfilter->dlist[out].name);
1564 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1565 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1566 }
1567 else
1568 {
1569 if (pfilter->dlist[out].name)
1570 free (pfilter->dlist[out].name);
1571 pfilter->dlist[out].name = NULL;
1572 pfilter->dlist[out].alist = NULL;
1573 }
1574 if (gfilter->plist[out].name)
1575 {
1576 if (pfilter->plist[out].name)
1577 free (pfilter->plist[out].name);
1578 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1579 pfilter->plist[out].plist = gfilter->plist[out].plist;
1580 }
1581 else
1582 {
1583 if (pfilter->plist[out].name)
1584 free (pfilter->plist[out].name);
1585 pfilter->plist[out].name = NULL;
1586 pfilter->plist[out].plist = NULL;
1587 }
1588 if (gfilter->aslist[out].name)
1589 {
1590 if (pfilter->aslist[out].name)
1591 free (pfilter->aslist[out].name);
1592 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1593 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1594 }
1595 else
1596 {
1597 if (pfilter->aslist[out].name)
1598 free (pfilter->aslist[out].name);
1599 pfilter->aslist[out].name = NULL;
1600 pfilter->aslist[out].aslist = NULL;
1601 }
paulfee0f4c2004-09-13 05:12:46 +00001602 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001603 {
paulfee0f4c2004-09-13 05:12:46 +00001604 if (pfilter->map[RMAP_OUT].name)
1605 free (pfilter->map[RMAP_OUT].name);
1606 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1607 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001608 }
1609 else
1610 {
paulfee0f4c2004-09-13 05:12:46 +00001611 if (pfilter->map[RMAP_OUT].name)
1612 free (pfilter->map[RMAP_OUT].name);
1613 pfilter->map[RMAP_OUT].name = NULL;
1614 pfilter->map[RMAP_OUT].map = NULL;
1615 }
1616
1617 /* RS-client's import/export route-maps. */
1618 if (gfilter->map[RMAP_IMPORT].name)
1619 {
1620 if (pfilter->map[RMAP_IMPORT].name)
1621 free (pfilter->map[RMAP_IMPORT].name);
1622 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1623 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1624 }
1625 else
1626 {
1627 if (pfilter->map[RMAP_IMPORT].name)
1628 free (pfilter->map[RMAP_IMPORT].name);
1629 pfilter->map[RMAP_IMPORT].name = NULL;
1630 pfilter->map[RMAP_IMPORT].map = NULL;
1631 }
1632 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1633 {
1634 if (pfilter->map[RMAP_EXPORT].name)
1635 free (pfilter->map[RMAP_EXPORT].name);
1636 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1637 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001638 }
1639
1640 if (gfilter->usmap.name)
1641 {
1642 if (pfilter->usmap.name)
1643 free (pfilter->usmap.name);
1644 pfilter->usmap.name = strdup (gfilter->usmap.name);
1645 pfilter->usmap.map = gfilter->usmap.map;
1646 }
1647 else
1648 {
1649 if (pfilter->usmap.name)
1650 free (pfilter->usmap.name);
1651 pfilter->usmap.name = NULL;
1652 pfilter->usmap.map = NULL;
1653 }
1654}
1655
1656/* Peer group's remote AS configuration. */
1657int
paulfd79ac92004-10-13 05:06:08 +00001658peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001659{
1660 struct peer_group *group;
1661 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001662 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001663
1664 group = peer_group_lookup (bgp, group_name);
1665 if (! group)
1666 return -1;
1667
1668 if (group->conf->as == *as)
1669 return 0;
1670
1671 /* When we setup peer-group AS number all peer group member's AS
1672 number must be updated to same number. */
1673 peer_as_change (group->conf, *as);
1674
paul1eb8ef22005-04-07 07:30:20 +00001675 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001676 {
1677 if (peer->as != *as)
1678 peer_as_change (peer, *as);
1679 }
1680
1681 return 0;
1682}
1683
1684int
1685peer_group_delete (struct peer_group *group)
1686{
1687 struct bgp *bgp;
1688 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001689 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001690
1691 bgp = group->bgp;
1692
paul1eb8ef22005-04-07 07:30:20 +00001693 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001694 {
1695 peer->group = NULL;
1696 peer_delete (peer);
1697 }
1698 list_delete (group->peer);
1699
1700 free (group->name);
1701 group->name = NULL;
1702
1703 group->conf->group = NULL;
1704 peer_delete (group->conf);
1705
1706 /* Delete from all peer_group list. */
1707 listnode_delete (bgp->group, group);
1708
1709 peer_group_free (group);
1710
1711 return 0;
1712}
1713
1714int
1715peer_group_remote_as_delete (struct peer_group *group)
1716{
1717 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001718 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001719
1720 if (! group->conf->as)
1721 return 0;
1722
paul1eb8ef22005-04-07 07:30:20 +00001723 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001724 {
1725 peer->group = NULL;
1726 peer_delete (peer);
1727 }
1728 list_delete_all_node (group->peer);
1729
1730 group->conf->as = 0;
1731
1732 return 0;
1733}
1734
1735/* Bind specified peer to peer group. */
1736int
1737peer_group_bind (struct bgp *bgp, union sockunion *su,
1738 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1739{
1740 struct peer *peer;
1741 int first_member = 0;
1742
1743 /* Check peer group's address family. */
1744 if (! group->conf->afc[afi][safi])
1745 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1746
1747 /* Lookup the peer. */
1748 peer = peer_lookup (bgp, su);
1749
1750 /* Create a new peer. */
1751 if (! peer)
1752 {
1753 if (! group->conf->as)
1754 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1755
1756 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1757 peer->group = group;
1758 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001759
Paul Jakmaca058a32006-09-14 02:58:49 +00001760 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001761 listnode_add (group->peer, peer);
1762 peer_group2peer_config_copy (group, peer, afi, safi);
1763
1764 return 0;
1765 }
1766
1767 /* When the peer already belongs to peer group, check the consistency. */
1768 if (peer->af_group[afi][safi])
1769 {
1770 if (strcmp (peer->group->name, group->name) != 0)
1771 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1772
1773 return 0;
1774 }
1775
1776 /* Check current peer group configuration. */
1777 if (peer_group_active (peer)
1778 && strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_MISMATCH;
1780
1781 if (! group->conf->as)
1782 {
1783 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1784 && peer_sort (group->conf) != peer_sort (peer))
1785 {
1786 if (as)
1787 *as = peer->as;
1788 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1789 }
1790
1791 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1792 first_member = 1;
1793 }
1794
1795 peer->af_group[afi][safi] = 1;
1796 peer->afc[afi][safi] = 1;
1797 if (! peer->group)
1798 {
1799 peer->group = group;
paul200df112005-06-01 11:17:05 +00001800
Paul Jakmaca058a32006-09-14 02:58:49 +00001801 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001802 listnode_add (group->peer, peer);
1803 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001804 else
1805 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001806
1807 if (first_member)
1808 {
1809 /* Advertisement-interval reset */
1810 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1811 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1812 else
1813 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1814
1815 /* ebgp-multihop reset */
1816 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1817 group->conf->ttl = 255;
1818
1819 /* local-as reset */
1820 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1821 {
1822 group->conf->change_local_as = 0;
1823 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1824 }
1825 }
paulfee0f4c2004-09-13 05:12:46 +00001826
1827 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1828 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001829 struct listnode *pn;
1830
paulfee0f4c2004-09-13 05:12:46 +00001831 /* If it's not configured as RSERVER_CLIENT in any other address
1832 family, without being member of a peer_group, remove it from
1833 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001834 if (! peer_rsclient_active (peer)
1835 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001836 {
1837 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001839
1840 /* Clear our own rsclient rib for this afi/safi. */
1841 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001842 }
paulfee0f4c2004-09-13 05:12:46 +00001843
Paul Jakmab608d5b2008-07-02 02:12:07 +00001844 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001845
1846 /* Import policy. */
1847 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1848 {
1849 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1850 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1851 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1852 }
1853
1854 /* Export policy. */
1855 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1856 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1859 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1861 }
1862 }
1863
paul718e3742002-12-13 20:15:29 +00001864 peer_group2peer_config_copy (group, peer, afi, safi);
1865
1866 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001867 {
1868 peer->last_reset = PEER_DOWN_RMAP_BIND;
1869 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1870 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1871 }
paul718e3742002-12-13 20:15:29 +00001872 else
1873 BGP_EVENT_ADD (peer, BGP_Stop);
1874
1875 return 0;
1876}
1877
1878int
1879peer_group_unbind (struct bgp *bgp, struct peer *peer,
1880 struct peer_group *group, afi_t afi, safi_t safi)
1881{
1882 if (! peer->af_group[afi][safi])
1883 return 0;
1884
1885 if (group != peer->group)
1886 return BGP_ERR_PEER_GROUP_MISMATCH;
1887
1888 peer->af_group[afi][safi] = 0;
1889 peer->afc[afi][safi] = 0;
1890 peer_af_flag_reset (peer, afi, safi);
1891
paulfee0f4c2004-09-13 05:12:46 +00001892 if (peer->rib[afi][safi])
1893 peer->rib[afi][safi] = NULL;
1894
paul718e3742002-12-13 20:15:29 +00001895 if (! peer_group_active (peer))
1896 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001897 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001898 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001899 listnode_delete (group->peer, peer);
1900 peer->group = NULL;
1901 if (group->conf->as)
1902 {
1903 peer_delete (peer);
1904 return 0;
1905 }
1906 peer_global_config_reset (peer);
1907 }
1908
1909 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001910 {
1911 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1912 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1913 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1914 }
paul718e3742002-12-13 20:15:29 +00001915 else
1916 BGP_EVENT_ADD (peer, BGP_Stop);
1917
1918 return 0;
1919}
1920
1921/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001922static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001923bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001924{
1925 struct bgp *bgp;
1926 afi_t afi;
1927 safi_t safi;
1928
paul200df112005-06-01 11:17:05 +00001929 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1930 return NULL;
1931
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001932 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001933 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001934 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001935
1936 bgp->peer = list_new ();
1937 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1938
1939 bgp->group = list_new ();
1940 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1941
paulfee0f4c2004-09-13 05:12:46 +00001942 bgp->rsclient = list_new ();
1943 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1944
paul718e3742002-12-13 20:15:29 +00001945 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1946 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1947 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001948 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1949 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1950 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001951 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1952 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001953 }
1954
1955 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1956 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1957 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001958 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1959 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001960
1961 bgp->as = *as;
1962
1963 if (name)
1964 bgp->name = strdup (name);
1965
1966 return bgp;
1967}
1968
1969/* Return first entry of BGP. */
1970struct bgp *
paul94f2b392005-06-28 12:44:16 +00001971bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001972{
1973 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001974 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001975 return NULL;
1976}
1977
1978/* Lookup BGP entry. */
1979struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001980bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001981{
1982 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001984
paul1eb8ef22005-04-07 07:30:20 +00001985 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001986 if (bgp->as == as
1987 && ((bgp->name == NULL && name == NULL)
1988 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1989 return bgp;
1990 return NULL;
1991}
1992
1993/* Lookup BGP structure by view name. */
1994struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001995bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001996{
1997 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001998 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001999
paul1eb8ef22005-04-07 07:30:20 +00002000 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002001 if ((bgp->name == NULL && name == NULL)
2002 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2003 return bgp;
2004 return NULL;
2005}
2006
2007/* Called from VTY commands. */
2008int
paulfd79ac92004-10-13 05:06:08 +00002009bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002010{
2011 struct bgp *bgp;
2012
2013 /* Multiple instance check. */
2014 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2015 {
2016 if (name)
2017 bgp = bgp_lookup_by_name (name);
2018 else
2019 bgp = bgp_get_default ();
2020
2021 /* Already exists. */
2022 if (bgp)
2023 {
2024 if (bgp->as != *as)
2025 {
2026 *as = bgp->as;
2027 return BGP_ERR_INSTANCE_MISMATCH;
2028 }
2029 *bgp_val = bgp;
2030 return 0;
2031 }
2032 }
2033 else
2034 {
2035 /* BGP instance name can not be specified for single instance. */
2036 if (name)
2037 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2038
2039 /* Get default BGP structure if exists. */
2040 bgp = bgp_get_default ();
2041
2042 if (bgp)
2043 {
2044 if (bgp->as != *as)
2045 {
2046 *as = bgp->as;
2047 return BGP_ERR_AS_MISMATCH;
2048 }
2049 *bgp_val = bgp;
2050 return 0;
2051 }
2052 }
2053
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002054 /* Create BGP server socket, if first instance. */
2055 if (list_isempty(bm->bgp))
2056 {
2057 if (bgp_socket (bm->port, bm->address) < 0)
2058 return BGP_ERR_INVALID_VALUE;
2059 }
2060
paul718e3742002-12-13 20:15:29 +00002061 bgp = bgp_create (as, name);
2062 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002063 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002064 *bgp_val = bgp;
2065
2066 return 0;
2067}
2068
2069/* Delete BGP instance. */
2070int
2071bgp_delete (struct bgp *bgp)
2072{
2073 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002074 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002075 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002076 struct listnode *next;
2077 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002078 int i;
2079
2080 /* Delete static route. */
2081 bgp_static_delete (bgp);
2082
2083 /* Unset redistribution. */
2084 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2085 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2086 if (i != ZEBRA_ROUTE_BGP)
2087 bgp_redistribute_unset (bgp, afi, i);
2088
paul1eb8ef22005-04-07 07:30:20 +00002089 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2090 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002091
Chris Caputo228da422009-07-18 05:44:03 +00002092 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2093 peer_group_delete (group);
2094
2095 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002096
2097 if (bgp->peer_self) {
2098 peer_delete(bgp->peer_self);
2099 bgp->peer_self = NULL;
2100 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002101
2102 /* Remove visibility via the master list - there may however still be
2103 * routes to be processed still referencing the struct bgp.
2104 */
2105 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002106 if (list_isempty(bm->bgp))
2107 bgp_close ();
2108
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002109 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002110
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002111 return 0;
2112}
2113
2114static void bgp_free (struct bgp *);
2115
2116void
2117bgp_lock (struct bgp *bgp)
2118{
2119 ++bgp->lock;
2120}
2121
2122void
2123bgp_unlock(struct bgp *bgp)
2124{
Chris Caputo228da422009-07-18 05:44:03 +00002125 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002126 if (--bgp->lock == 0)
2127 bgp_free (bgp);
2128}
2129
2130static void
2131bgp_free (struct bgp *bgp)
2132{
2133 afi_t afi;
2134 safi_t safi;
2135
2136 list_delete (bgp->group);
2137 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002138 list_delete (bgp->rsclient);
2139
paul718e3742002-12-13 20:15:29 +00002140 if (bgp->name)
2141 free (bgp->name);
2142
2143 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2144 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2145 {
2146 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002147 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002148 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002149 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002150 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002151 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002152 }
2153 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002154}
2155
2156struct peer *
2157peer_lookup (struct bgp *bgp, union sockunion *su)
2158{
2159 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002160 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002161
Steve Hillfc4dc592009-07-28 17:54:35 +01002162 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002163 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002164 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2165 if (sockunion_same (&peer->su, su)
2166 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2167 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002168 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002169 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002170 {
2171 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002172
Paul Jakma2158ad22009-07-28 18:10:55 +01002173 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2175 if (sockunion_same (&peer->su, su)
2176 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2177 return peer;
paul718e3742002-12-13 20:15:29 +00002178 }
2179 return NULL;
2180}
2181
2182struct peer *
2183peer_lookup_with_open (union sockunion *su, as_t remote_as,
2184 struct in_addr *remote_id, int *as)
2185{
2186 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002187 struct listnode *node;
2188 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002189 struct bgp *bgp;
2190
Steve Hillfc4dc592009-07-28 17:54:35 +01002191 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002192 return NULL;
2193
Paul Jakma9d878772009-08-05 16:25:16 +01002194 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002195 {
Paul Jakma9d878772009-08-05 16:25:16 +01002196 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2197 {
2198 if (sockunion_same (&peer->su, su)
2199 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2200 {
2201 if (peer->as == remote_as
2202 && peer->remote_id.s_addr == remote_id->s_addr)
2203 return peer;
2204 if (peer->as == remote_as)
2205 *as = 1;
2206 }
2207 }
2208
2209 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2210 {
2211 if (sockunion_same (&peer->su, su)
2212 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2213 {
2214 if (peer->as == remote_as
2215 && peer->remote_id.s_addr == 0)
2216 return peer;
2217 if (peer->as == remote_as)
2218 *as = 1;
2219 }
2220 }
paul718e3742002-12-13 20:15:29 +00002221 }
2222 return NULL;
2223}
2224
2225/* If peer is configured at least one address family return 1. */
2226int
2227peer_active (struct peer *peer)
2228{
2229 if (peer->afc[AFI_IP][SAFI_UNICAST]
2230 || peer->afc[AFI_IP][SAFI_MULTICAST]
2231 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2232 || peer->afc[AFI_IP6][SAFI_UNICAST]
2233 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2234 return 1;
2235 return 0;
2236}
2237
2238/* If peer is negotiated at least one address family return 1. */
2239int
2240peer_active_nego (struct peer *peer)
2241{
2242 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2243 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2244 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2245 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2246 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2247 return 1;
2248 return 0;
2249}
2250
2251/* peer_flag_change_type. */
2252enum peer_change_type
2253{
2254 peer_change_none,
2255 peer_change_reset,
2256 peer_change_reset_in,
2257 peer_change_reset_out,
2258};
2259
paul94f2b392005-06-28 12:44:16 +00002260static void
paul718e3742002-12-13 20:15:29 +00002261peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2262 enum peer_change_type type)
2263{
2264 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2265 return;
2266
2267 if (type == peer_change_reset)
2268 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2269 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2270 else if (type == peer_change_reset_in)
2271 {
2272 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2273 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2274 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2275 else
2276 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2277 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2278 }
2279 else if (type == peer_change_reset_out)
2280 bgp_announce_route (peer, afi, safi);
2281}
2282
2283struct peer_flag_action
2284{
2285 /* Peer's flag. */
2286 u_int32_t flag;
2287
2288 /* This flag can be set for peer-group member. */
2289 u_char not_for_member;
2290
2291 /* Action when the flag is changed. */
2292 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002293
2294 /* Peer down cause */
2295 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002296};
2297
Stephen Hemminger03621952009-07-21 16:27:20 -07002298static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002299 {
2300 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2301 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2302 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2303 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2304 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002305 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002306 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002307 { 0, 0, 0 }
2308 };
2309
Stephen Hemminger03621952009-07-21 16:27:20 -07002310static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002311 {
2312 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2313 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2314 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2315 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2316 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2317 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2318 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2319 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2320 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2321 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2322 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2323 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2324 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002325 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002326 { 0, 0, 0 }
2327 };
2328
2329/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002330static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002331peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002332 struct peer_flag_action *action, u_int32_t flag)
2333{
2334 int i;
2335 int found = 0;
2336 int reset_in = 0;
2337 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002338 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002339
2340 /* Check peer's frag action. */
2341 for (i = 0; i < size; i++)
2342 {
2343 match = &action_list[i];
2344
2345 if (match->flag == 0)
2346 break;
2347
2348 if (match->flag & flag)
2349 {
2350 found = 1;
2351
2352 if (match->type == peer_change_reset_in)
2353 reset_in = 1;
2354 if (match->type == peer_change_reset_out)
2355 reset_out = 1;
2356 if (match->type == peer_change_reset)
2357 {
2358 reset_in = 1;
2359 reset_out = 1;
2360 }
2361 if (match->not_for_member)
2362 action->not_for_member = 1;
2363 }
2364 }
2365
2366 /* Set peer clear type. */
2367 if (reset_in && reset_out)
2368 action->type = peer_change_reset;
2369 else if (reset_in)
2370 action->type = peer_change_reset_in;
2371 else if (reset_out)
2372 action->type = peer_change_reset_out;
2373 else
2374 action->type = peer_change_none;
2375
2376 return found;
2377}
2378
paul94f2b392005-06-28 12:44:16 +00002379static void
paul718e3742002-12-13 20:15:29 +00002380peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2381{
2382 if (flag == PEER_FLAG_SHUTDOWN)
2383 {
2384 if (CHECK_FLAG (peer->flags, flag))
2385 {
hasso93406d82005-02-02 14:40:33 +00002386 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2387 peer_nsf_stop (peer);
2388
hasso0a486e52005-02-01 20:57:17 +00002389 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2390 if (peer->t_pmax_restart)
2391 {
2392 BGP_TIMER_OFF (peer->t_pmax_restart);
2393 if (BGP_DEBUG (events, EVENTS))
2394 zlog_debug ("%s Maximum-prefix restart timer canceled",
2395 peer->host);
2396 }
2397
hasso93406d82005-02-02 14:40:33 +00002398 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2399 peer_nsf_stop (peer);
2400
paul718e3742002-12-13 20:15:29 +00002401 if (peer->status == Established)
2402 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2403 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2404 else
2405 BGP_EVENT_ADD (peer, BGP_Stop);
2406 }
2407 else
2408 {
2409 peer->v_start = BGP_INIT_START_TIMER;
2410 BGP_EVENT_ADD (peer, BGP_Stop);
2411 }
2412 }
2413 else if (peer->status == Established)
2414 {
hassoc9502432005-02-01 22:01:48 +00002415 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2416 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2417 else if (flag == PEER_FLAG_PASSIVE)
2418 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002419 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002420 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002421
hassoc9502432005-02-01 22:01:48 +00002422 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2423 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002424 }
2425 else
2426 BGP_EVENT_ADD (peer, BGP_Stop);
2427}
2428
2429/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002430static int
paul718e3742002-12-13 20:15:29 +00002431peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2432{
2433 int found;
2434 int size;
2435 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002436 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002437 struct peer_flag_action action;
2438
2439 memset (&action, 0, sizeof (struct peer_flag_action));
2440 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2441
2442 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2443
2444 /* No flag action is found. */
2445 if (! found)
2446 return BGP_ERR_INVALID_FLAG;
2447
2448 /* Not for peer-group member. */
2449 if (action.not_for_member && peer_group_active (peer))
2450 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2451
2452 /* When unset the peer-group member's flag we have to check
2453 peer-group configuration. */
2454 if (! set && peer_group_active (peer))
2455 if (CHECK_FLAG (peer->group->conf->flags, flag))
2456 {
2457 if (flag == PEER_FLAG_SHUTDOWN)
2458 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2459 else
2460 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2461 }
2462
2463 /* Flag conflict check. */
2464 if (set
2465 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2466 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2467 return BGP_ERR_PEER_FLAG_CONFLICT;
2468
2469 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2470 {
2471 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2472 return 0;
2473 if (! set && ! CHECK_FLAG (peer->flags, flag))
2474 return 0;
2475 }
2476
2477 if (set)
2478 SET_FLAG (peer->flags, flag);
2479 else
2480 UNSET_FLAG (peer->flags, flag);
2481
2482 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2483 {
2484 if (action.type == peer_change_reset)
2485 peer_flag_modify_action (peer, flag);
2486
2487 return 0;
2488 }
2489
2490 /* peer-group member updates. */
2491 group = peer->group;
2492
paul1eb8ef22005-04-07 07:30:20 +00002493 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002494 {
2495 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2496 continue;
2497
2498 if (! set && ! CHECK_FLAG (peer->flags, flag))
2499 continue;
2500
2501 if (set)
2502 SET_FLAG (peer->flags, flag);
2503 else
2504 UNSET_FLAG (peer->flags, flag);
2505
2506 if (action.type == peer_change_reset)
2507 peer_flag_modify_action (peer, flag);
2508 }
2509 return 0;
2510}
2511
2512int
2513peer_flag_set (struct peer *peer, u_int32_t flag)
2514{
2515 return peer_flag_modify (peer, flag, 1);
2516}
2517
2518int
2519peer_flag_unset (struct peer *peer, u_int32_t flag)
2520{
2521 return peer_flag_modify (peer, flag, 0);
2522}
2523
paul94f2b392005-06-28 12:44:16 +00002524static int
paul718e3742002-12-13 20:15:29 +00002525peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2526{
2527 if (peer->af_group[afi][safi])
2528 return 1;
2529 return 0;
2530}
2531
paul94f2b392005-06-28 12:44:16 +00002532static int
paul718e3742002-12-13 20:15:29 +00002533peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2534 int set)
2535{
2536 int found;
2537 int size;
paul1eb8ef22005-04-07 07:30:20 +00002538 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002539 struct peer_group *group;
2540 struct peer_flag_action action;
2541
2542 memset (&action, 0, sizeof (struct peer_flag_action));
2543 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2544
2545 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2546
2547 /* No flag action is found. */
2548 if (! found)
2549 return BGP_ERR_INVALID_FLAG;
2550
2551 /* Adress family must be activated. */
2552 if (! peer->afc[afi][safi])
2553 return BGP_ERR_PEER_INACTIVE;
2554
2555 /* Not for peer-group member. */
2556 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2557 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2558
2559 /* Spcecial check for reflector client. */
2560 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2561 && peer_sort (peer) != BGP_PEER_IBGP)
2562 return BGP_ERR_NOT_INTERNAL_PEER;
2563
2564 /* Spcecial check for remove-private-AS. */
2565 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2566 && peer_sort (peer) == BGP_PEER_IBGP)
2567 return BGP_ERR_REMOVE_PRIVATE_AS;
2568
2569 /* When unset the peer-group member's flag we have to check
2570 peer-group configuration. */
2571 if (! set && peer->af_group[afi][safi])
2572 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2573 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2574
2575 /* When current flag configuration is same as requested one. */
2576 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2577 {
2578 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2579 return 0;
2580 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2581 return 0;
2582 }
2583
2584 if (set)
2585 SET_FLAG (peer->af_flags[afi][safi], flag);
2586 else
2587 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2588
2589 /* Execute action when peer is established. */
2590 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2591 && peer->status == Established)
2592 {
2593 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2594 bgp_clear_adj_in (peer, afi, safi);
2595 else
hassoe0701b72004-05-20 09:19:34 +00002596 {
2597 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2598 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2599 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2600 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2601 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2602 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2603 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2604 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2605
2606 peer_change_action (peer, afi, safi, action.type);
2607 }
2608
paul718e3742002-12-13 20:15:29 +00002609 }
2610
2611 /* Peer group member updates. */
2612 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2613 {
2614 group = peer->group;
2615
paul1eb8ef22005-04-07 07:30:20 +00002616 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002617 {
2618 if (! peer->af_group[afi][safi])
2619 continue;
2620
2621 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2622 continue;
2623
2624 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2625 continue;
2626
2627 if (set)
2628 SET_FLAG (peer->af_flags[afi][safi], flag);
2629 else
2630 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2631
2632 if (peer->status == Established)
2633 {
2634 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2635 bgp_clear_adj_in (peer, afi, safi);
2636 else
hassoe0701b72004-05-20 09:19:34 +00002637 {
2638 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2639 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2640 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2641 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2642 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2643 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2644 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2645 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2646
2647 peer_change_action (peer, afi, safi, action.type);
2648 }
paul718e3742002-12-13 20:15:29 +00002649 }
2650 }
2651 }
2652 return 0;
2653}
2654
2655int
2656peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2657{
2658 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2659}
2660
2661int
2662peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2663{
2664 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2665}
2666
2667/* EBGP multihop configuration. */
2668int
2669peer_ebgp_multihop_set (struct peer *peer, int ttl)
2670{
2671 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002672 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002673 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002674
2675 if (peer_sort (peer) == BGP_PEER_IBGP)
2676 return 0;
2677
Nick Hilliardfa411a22011-03-23 15:33:17 +00002678 /* see comment in peer_ttl_security_hops_set() */
2679 if (ttl != MAXTTL)
2680 {
2681 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2682 {
2683 group = peer->group;
2684 if (group->conf->gtsm_hops != 0)
2685 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2686
2687 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2688 {
2689 if (peer_sort (peer1) == BGP_PEER_IBGP)
2690 continue;
2691
2692 if (peer1->gtsm_hops != 0)
2693 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2694 }
2695 }
2696 else
2697 {
2698 if (peer->gtsm_hops != 0)
2699 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2700 }
2701 }
2702
paul718e3742002-12-13 20:15:29 +00002703 peer->ttl = ttl;
2704
2705 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2706 {
pauleb821182004-05-01 08:44:08 +00002707 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2708 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002709 }
2710 else
2711 {
2712 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002713 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002714 {
2715 if (peer_sort (peer) == BGP_PEER_IBGP)
2716 continue;
paul718e3742002-12-13 20:15:29 +00002717
pauleb821182004-05-01 08:44:08 +00002718 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002719
pauleb821182004-05-01 08:44:08 +00002720 if (peer->fd >= 0)
2721 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2722 }
paul718e3742002-12-13 20:15:29 +00002723 }
2724 return 0;
2725}
2726
2727int
2728peer_ebgp_multihop_unset (struct peer *peer)
2729{
2730 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002731 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002732
2733 if (peer_sort (peer) == BGP_PEER_IBGP)
2734 return 0;
2735
Nick Hilliardfa411a22011-03-23 15:33:17 +00002736 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2737 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2738
paul718e3742002-12-13 20:15:29 +00002739 if (peer_group_active (peer))
2740 peer->ttl = peer->group->conf->ttl;
2741 else
2742 peer->ttl = 1;
2743
2744 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2745 {
pauleb821182004-05-01 08:44:08 +00002746 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2747 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002748 }
2749 else
2750 {
2751 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002752 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002753 {
2754 if (peer_sort (peer) == BGP_PEER_IBGP)
2755 continue;
paul718e3742002-12-13 20:15:29 +00002756
pauleb821182004-05-01 08:44:08 +00002757 peer->ttl = 1;
2758
2759 if (peer->fd >= 0)
2760 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2761 }
paul718e3742002-12-13 20:15:29 +00002762 }
2763 return 0;
2764}
2765
2766/* Neighbor description. */
2767int
2768peer_description_set (struct peer *peer, char *desc)
2769{
2770 if (peer->desc)
2771 XFREE (MTYPE_PEER_DESC, peer->desc);
2772
2773 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2774
2775 return 0;
2776}
2777
2778int
2779peer_description_unset (struct peer *peer)
2780{
2781 if (peer->desc)
2782 XFREE (MTYPE_PEER_DESC, peer->desc);
2783
2784 peer->desc = NULL;
2785
2786 return 0;
2787}
2788
2789/* Neighbor update-source. */
2790int
paulfd79ac92004-10-13 05:06:08 +00002791peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002792{
2793 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002794 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002795
2796 if (peer->update_if)
2797 {
2798 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2799 && strcmp (peer->update_if, ifname) == 0)
2800 return 0;
2801
2802 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2803 peer->update_if = NULL;
2804 }
2805
2806 if (peer->update_source)
2807 {
2808 sockunion_free (peer->update_source);
2809 peer->update_source = NULL;
2810 }
2811
2812 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2813
2814 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2815 {
2816 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002817 {
2818 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2819 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2820 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2821 }
paul718e3742002-12-13 20:15:29 +00002822 else
2823 BGP_EVENT_ADD (peer, BGP_Stop);
2824 return 0;
2825 }
2826
2827 /* peer-group member updates. */
2828 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002829 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002830 {
2831 if (peer->update_if)
2832 {
2833 if (strcmp (peer->update_if, ifname) == 0)
2834 continue;
2835
2836 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2837 peer->update_if = NULL;
2838 }
2839
2840 if (peer->update_source)
2841 {
2842 sockunion_free (peer->update_source);
2843 peer->update_source = NULL;
2844 }
2845
2846 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2847
2848 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002849 {
2850 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2851 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2852 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2853 }
paul718e3742002-12-13 20:15:29 +00002854 else
2855 BGP_EVENT_ADD (peer, BGP_Stop);
2856 }
2857 return 0;
2858}
2859
2860int
2861peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2862{
2863 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002864 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002865
2866 if (peer->update_source)
2867 {
2868 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2869 && sockunion_cmp (peer->update_source, su) == 0)
2870 return 0;
2871 sockunion_free (peer->update_source);
2872 peer->update_source = NULL;
2873 }
2874
2875 if (peer->update_if)
2876 {
2877 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2878 peer->update_if = NULL;
2879 }
2880
2881 peer->update_source = sockunion_dup (su);
2882
2883 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2884 {
2885 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002886 {
2887 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2888 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2889 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2890 }
paul718e3742002-12-13 20:15:29 +00002891 else
2892 BGP_EVENT_ADD (peer, BGP_Stop);
2893 return 0;
2894 }
2895
2896 /* peer-group member updates. */
2897 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002898 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002899 {
2900 if (peer->update_source)
2901 {
2902 if (sockunion_cmp (peer->update_source, su) == 0)
2903 continue;
2904 sockunion_free (peer->update_source);
2905 peer->update_source = NULL;
2906 }
2907
2908 if (peer->update_if)
2909 {
2910 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2911 peer->update_if = NULL;
2912 }
2913
2914 peer->update_source = sockunion_dup (su);
2915
2916 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002917 {
2918 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2919 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2920 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2921 }
paul718e3742002-12-13 20:15:29 +00002922 else
2923 BGP_EVENT_ADD (peer, BGP_Stop);
2924 }
2925 return 0;
2926}
2927
2928int
2929peer_update_source_unset (struct peer *peer)
2930{
2931 union sockunion *su;
2932 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002933 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002934
2935 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2936 && ! peer->update_source
2937 && ! peer->update_if)
2938 return 0;
2939
2940 if (peer->update_source)
2941 {
2942 sockunion_free (peer->update_source);
2943 peer->update_source = NULL;
2944 }
2945 if (peer->update_if)
2946 {
2947 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2948 peer->update_if = NULL;
2949 }
2950
2951 if (peer_group_active (peer))
2952 {
2953 group = peer->group;
2954
2955 if (group->conf->update_source)
2956 {
2957 su = sockunion_dup (group->conf->update_source);
2958 peer->update_source = su;
2959 }
2960 else if (group->conf->update_if)
2961 peer->update_if =
2962 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2963 }
2964
2965 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2966 {
2967 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002968 {
2969 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2970 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2971 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2972 }
paul718e3742002-12-13 20:15:29 +00002973 else
2974 BGP_EVENT_ADD (peer, BGP_Stop);
2975 return 0;
2976 }
2977
2978 /* peer-group member updates. */
2979 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002980 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002981 {
2982 if (! peer->update_source && ! peer->update_if)
2983 continue;
2984
2985 if (peer->update_source)
2986 {
2987 sockunion_free (peer->update_source);
2988 peer->update_source = NULL;
2989 }
2990
2991 if (peer->update_if)
2992 {
2993 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2994 peer->update_if = NULL;
2995 }
2996
2997 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002998 {
2999 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3000 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3001 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3002 }
paul718e3742002-12-13 20:15:29 +00003003 else
3004 BGP_EVENT_ADD (peer, BGP_Stop);
3005 }
3006 return 0;
3007}
3008
3009int
3010peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003011 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003012{
3013 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003014 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003015
3016 /* Adress family must be activated. */
3017 if (! peer->afc[afi][safi])
3018 return BGP_ERR_PEER_INACTIVE;
3019
3020 /* Default originate can't be used for peer group memeber. */
3021 if (peer_is_group_member (peer, afi, safi))
3022 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3023
3024 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3025 || (rmap && ! peer->default_rmap[afi][safi].name)
3026 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3027 {
3028 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3029
3030 if (rmap)
3031 {
3032 if (peer->default_rmap[afi][safi].name)
3033 free (peer->default_rmap[afi][safi].name);
3034 peer->default_rmap[afi][safi].name = strdup (rmap);
3035 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3036 }
3037 }
3038
3039 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3040 {
3041 if (peer->status == Established && peer->afc_nego[afi][safi])
3042 bgp_default_originate (peer, afi, safi, 0);
3043 return 0;
3044 }
3045
3046 /* peer-group member updates. */
3047 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003048 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003049 {
3050 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3051
3052 if (rmap)
3053 {
3054 if (peer->default_rmap[afi][safi].name)
3055 free (peer->default_rmap[afi][safi].name);
3056 peer->default_rmap[afi][safi].name = strdup (rmap);
3057 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3058 }
3059
3060 if (peer->status == Established && peer->afc_nego[afi][safi])
3061 bgp_default_originate (peer, afi, safi, 0);
3062 }
3063 return 0;
3064}
3065
3066int
3067peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3068{
3069 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003070 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003071
3072 /* Adress family must be activated. */
3073 if (! peer->afc[afi][safi])
3074 return BGP_ERR_PEER_INACTIVE;
3075
3076 /* Default originate can't be used for peer group memeber. */
3077 if (peer_is_group_member (peer, afi, safi))
3078 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3079
3080 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3081 {
3082 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3083
3084 if (peer->default_rmap[afi][safi].name)
3085 free (peer->default_rmap[afi][safi].name);
3086 peer->default_rmap[afi][safi].name = NULL;
3087 peer->default_rmap[afi][safi].map = NULL;
3088 }
3089
3090 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3091 {
3092 if (peer->status == Established && peer->afc_nego[afi][safi])
3093 bgp_default_originate (peer, afi, safi, 1);
3094 return 0;
3095 }
3096
3097 /* peer-group member updates. */
3098 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003099 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003100 {
3101 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3102
3103 if (peer->default_rmap[afi][safi].name)
3104 free (peer->default_rmap[afi][safi].name);
3105 peer->default_rmap[afi][safi].name = NULL;
3106 peer->default_rmap[afi][safi].map = NULL;
3107
3108 if (peer->status == Established && peer->afc_nego[afi][safi])
3109 bgp_default_originate (peer, afi, safi, 1);
3110 }
3111 return 0;
3112}
3113
3114int
3115peer_port_set (struct peer *peer, u_int16_t port)
3116{
3117 peer->port = port;
3118 return 0;
3119}
3120
3121int
3122peer_port_unset (struct peer *peer)
3123{
3124 peer->port = BGP_PORT_DEFAULT;
3125 return 0;
3126}
3127
3128/* neighbor weight. */
3129int
3130peer_weight_set (struct peer *peer, u_int16_t weight)
3131{
3132 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003133 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003134
3135 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3136 peer->weight = weight;
3137
3138 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3139 return 0;
3140
3141 /* peer-group member updates. */
3142 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003143 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003144 {
3145 peer->weight = group->conf->weight;
3146 }
3147 return 0;
3148}
3149
3150int
3151peer_weight_unset (struct peer *peer)
3152{
3153 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003155
3156 /* Set default weight. */
3157 if (peer_group_active (peer))
3158 peer->weight = peer->group->conf->weight;
3159 else
3160 peer->weight = 0;
3161
3162 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3163
3164 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3165 return 0;
3166
3167 /* peer-group member updates. */
3168 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003169 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003170 {
3171 peer->weight = 0;
3172 }
3173 return 0;
3174}
3175
3176int
3177peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3178{
3179 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003180 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003181
3182 /* Not for peer group memeber. */
3183 if (peer_group_active (peer))
3184 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3185
3186 /* keepalive value check. */
3187 if (keepalive > 65535)
3188 return BGP_ERR_INVALID_VALUE;
3189
3190 /* Holdtime value check. */
3191 if (holdtime > 65535)
3192 return BGP_ERR_INVALID_VALUE;
3193
3194 /* Holdtime value must be either 0 or greater than 3. */
3195 if (holdtime < 3 && holdtime != 0)
3196 return BGP_ERR_INVALID_VALUE;
3197
3198 /* Set value to the configuration. */
3199 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3200 peer->holdtime = holdtime;
3201 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3202
3203 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3204 return 0;
3205
3206 /* peer-group member updates. */
3207 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003208 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003209 {
3210 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3211 peer->holdtime = group->conf->holdtime;
3212 peer->keepalive = group->conf->keepalive;
3213 }
3214 return 0;
3215}
3216
3217int
3218peer_timers_unset (struct peer *peer)
3219{
3220 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003221 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003222
3223 if (peer_group_active (peer))
3224 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3225
3226 /* Clear configuration. */
3227 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3228 peer->keepalive = 0;
3229 peer->holdtime = 0;
3230
3231 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3232 return 0;
3233
3234 /* peer-group member updates. */
3235 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003236 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003237 {
3238 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3239 peer->holdtime = 0;
3240 peer->keepalive = 0;
3241 }
3242
3243 return 0;
3244}
3245
3246int
3247peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3248{
3249 if (peer_group_active (peer))
3250 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3251
3252 if (connect > 65535)
3253 return BGP_ERR_INVALID_VALUE;
3254
3255 /* Set value to the configuration. */
3256 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3257 peer->connect = connect;
3258
3259 /* Set value to timer setting. */
3260 peer->v_connect = connect;
3261
3262 return 0;
3263}
3264
3265int
3266peer_timers_connect_unset (struct peer *peer)
3267{
3268 if (peer_group_active (peer))
3269 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3270
3271 /* Clear configuration. */
3272 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3273 peer->connect = 0;
3274
3275 /* Set timer setting to default value. */
3276 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3277
3278 return 0;
3279}
3280
3281int
3282peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3283{
3284 if (peer_group_active (peer))
3285 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3286
3287 if (routeadv > 600)
3288 return BGP_ERR_INVALID_VALUE;
3289
3290 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3291 peer->routeadv = routeadv;
3292 peer->v_routeadv = routeadv;
3293
3294 return 0;
3295}
3296
3297int
3298peer_advertise_interval_unset (struct peer *peer)
3299{
3300 if (peer_group_active (peer))
3301 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3302
3303 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3304 peer->routeadv = 0;
3305
3306 if (peer_sort (peer) == BGP_PEER_IBGP)
3307 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3308 else
3309 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3310
3311 return 0;
3312}
3313
paul718e3742002-12-13 20:15:29 +00003314/* neighbor interface */
3315int
paulfd79ac92004-10-13 05:06:08 +00003316peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003317{
3318 if (peer->ifname)
3319 free (peer->ifname);
3320 peer->ifname = strdup (str);
3321
3322 return 0;
3323}
3324
3325int
3326peer_interface_unset (struct peer *peer)
3327{
3328 if (peer->ifname)
3329 free (peer->ifname);
3330 peer->ifname = NULL;
3331
3332 return 0;
3333}
3334
3335/* Allow-as in. */
3336int
3337peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3338{
3339 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003340 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003341
3342 if (allow_num < 1 || allow_num > 10)
3343 return BGP_ERR_INVALID_VALUE;
3344
3345 if (peer->allowas_in[afi][safi] != allow_num)
3346 {
3347 peer->allowas_in[afi][safi] = allow_num;
3348 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3349 peer_change_action (peer, afi, safi, peer_change_reset_in);
3350 }
3351
3352 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3353 return 0;
3354
3355 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003356 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003357 {
3358 if (peer->allowas_in[afi][safi] != allow_num)
3359 {
3360 peer->allowas_in[afi][safi] = allow_num;
3361 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3362 peer_change_action (peer, afi, safi, peer_change_reset_in);
3363 }
3364
3365 }
3366 return 0;
3367}
3368
3369int
3370peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3371{
3372 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003373 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003374
3375 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3376 {
3377 peer->allowas_in[afi][safi] = 0;
3378 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3379 }
3380
3381 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3382 return 0;
3383
3384 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003385 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003386 {
3387 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3388 {
3389 peer->allowas_in[afi][safi] = 0;
3390 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3391 }
3392 }
3393 return 0;
3394}
3395
3396int
3397peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3398{
3399 struct bgp *bgp = peer->bgp;
3400 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003401 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003402
3403 if (peer_sort (peer) != BGP_PEER_EBGP
3404 && peer_sort (peer) != BGP_PEER_INTERNAL)
3405 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3406
3407 if (bgp->as == as)
3408 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3409
3410 if (peer_group_active (peer))
3411 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3412
3413 if (peer->change_local_as == as &&
3414 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3415 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3416 return 0;
3417
3418 peer->change_local_as = as;
3419 if (no_prepend)
3420 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3421 else
3422 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3423
3424 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3425 {
3426 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003427 {
3428 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3429 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3430 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3431 }
paul718e3742002-12-13 20:15:29 +00003432 else
3433 BGP_EVENT_ADD (peer, BGP_Stop);
3434
3435 return 0;
3436 }
3437
3438 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003439 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003440 {
3441 peer->change_local_as = as;
3442 if (no_prepend)
3443 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3444 else
3445 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3446
3447 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003448 {
3449 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3450 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3451 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3452 }
paul718e3742002-12-13 20:15:29 +00003453 else
3454 BGP_EVENT_ADD (peer, BGP_Stop);
3455 }
3456
3457 return 0;
3458}
3459
3460int
3461peer_local_as_unset (struct peer *peer)
3462{
3463 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003464 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003465
3466 if (peer_group_active (peer))
3467 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3468
3469 if (! peer->change_local_as)
3470 return 0;
3471
3472 peer->change_local_as = 0;
3473 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3474
3475 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3476 {
3477 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003478 {
3479 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3480 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3481 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3482 }
paul718e3742002-12-13 20:15:29 +00003483 else
3484 BGP_EVENT_ADD (peer, BGP_Stop);
3485
3486 return 0;
3487 }
3488
3489 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003490 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003491 {
3492 peer->change_local_as = 0;
3493 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3494
3495 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003496 {
3497 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3498 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3499 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3500 }
paul718e3742002-12-13 20:15:29 +00003501 else
3502 BGP_EVENT_ADD (peer, BGP_Stop);
3503 }
3504 return 0;
3505}
3506
Paul Jakma0df7c912008-07-21 21:02:49 +00003507/* Set password for authenticating with the peer. */
3508int
3509peer_password_set (struct peer *peer, const char *password)
3510{
3511 struct listnode *nn, *nnode;
3512 int len = password ? strlen(password) : 0;
3513 int ret = BGP_SUCCESS;
3514
3515 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3516 return BGP_ERR_INVALID_VALUE;
3517
3518 if (peer->password && strcmp (peer->password, password) == 0
3519 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3520 return 0;
3521
3522 if (peer->password)
3523 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3524
3525 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3526
3527 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3528 {
3529 if (peer->status == Established)
3530 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3531 else
3532 BGP_EVENT_ADD (peer, BGP_Stop);
3533
3534 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3535 }
3536
3537 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3538 {
3539 if (peer->password && strcmp (peer->password, password) == 0)
3540 continue;
3541
3542 if (peer->password)
3543 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3544
3545 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3546
3547 if (peer->status == Established)
3548 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3549 else
3550 BGP_EVENT_ADD (peer, BGP_Stop);
3551
3552 if (bgp_md5_set (peer) < 0)
3553 ret = BGP_ERR_TCPSIG_FAILED;
3554 }
3555
3556 return ret;
3557}
3558
3559int
3560peer_password_unset (struct peer *peer)
3561{
3562 struct listnode *nn, *nnode;
3563
3564 if (!peer->password
3565 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3566 return 0;
3567
3568 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3569 {
3570 if (peer_group_active (peer)
3571 && peer->group->conf->password
3572 && strcmp (peer->group->conf->password, peer->password) == 0)
3573 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3574
3575 if (peer->status == Established)
3576 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3577 else
3578 BGP_EVENT_ADD (peer, BGP_Stop);
3579
3580 if (peer->password)
3581 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3582
3583 peer->password = NULL;
3584
3585 bgp_md5_set (peer);
3586
3587 return 0;
3588 }
3589
3590 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3591 peer->password = NULL;
3592
3593 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3594 {
3595 if (!peer->password)
3596 continue;
3597
3598 if (peer->status == Established)
3599 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3600 else
3601 BGP_EVENT_ADD (peer, BGP_Stop);
3602
3603 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3604 peer->password = NULL;
3605
3606 bgp_md5_set (peer);
3607 }
3608
3609 return 0;
3610}
3611
paul718e3742002-12-13 20:15:29 +00003612/* Set distribute list to the peer. */
3613int
3614peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003615 const char *name)
paul718e3742002-12-13 20:15:29 +00003616{
3617 struct bgp_filter *filter;
3618 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003619 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003620
3621 if (! peer->afc[afi][safi])
3622 return BGP_ERR_PEER_INACTIVE;
3623
3624 if (direct != FILTER_IN && direct != FILTER_OUT)
3625 return BGP_ERR_INVALID_VALUE;
3626
3627 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3628 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3629
3630 filter = &peer->filter[afi][safi];
3631
3632 if (filter->plist[direct].name)
3633 return BGP_ERR_PEER_FILTER_CONFLICT;
3634
3635 if (filter->dlist[direct].name)
3636 free (filter->dlist[direct].name);
3637 filter->dlist[direct].name = strdup (name);
3638 filter->dlist[direct].alist = access_list_lookup (afi, name);
3639
3640 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3641 return 0;
3642
3643 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003644 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003645 {
3646 filter = &peer->filter[afi][safi];
3647
3648 if (! peer->af_group[afi][safi])
3649 continue;
3650
3651 if (filter->dlist[direct].name)
3652 free (filter->dlist[direct].name);
3653 filter->dlist[direct].name = strdup (name);
3654 filter->dlist[direct].alist = access_list_lookup (afi, name);
3655 }
3656
3657 return 0;
3658}
3659
3660int
3661peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3662{
3663 struct bgp_filter *filter;
3664 struct bgp_filter *gfilter;
3665 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003666 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003667
3668 if (! peer->afc[afi][safi])
3669 return BGP_ERR_PEER_INACTIVE;
3670
3671 if (direct != FILTER_IN && direct != FILTER_OUT)
3672 return BGP_ERR_INVALID_VALUE;
3673
3674 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3675 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3676
3677 filter = &peer->filter[afi][safi];
3678
3679 /* apply peer-group filter */
3680 if (peer->af_group[afi][safi])
3681 {
3682 gfilter = &peer->group->conf->filter[afi][safi];
3683
3684 if (gfilter->dlist[direct].name)
3685 {
3686 if (filter->dlist[direct].name)
3687 free (filter->dlist[direct].name);
3688 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3689 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3690 return 0;
3691 }
3692 }
3693
3694 if (filter->dlist[direct].name)
3695 free (filter->dlist[direct].name);
3696 filter->dlist[direct].name = NULL;
3697 filter->dlist[direct].alist = NULL;
3698
3699 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3700 return 0;
3701
3702 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003703 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003704 {
3705 filter = &peer->filter[afi][safi];
3706
3707 if (! peer->af_group[afi][safi])
3708 continue;
3709
3710 if (filter->dlist[direct].name)
3711 free (filter->dlist[direct].name);
3712 filter->dlist[direct].name = NULL;
3713 filter->dlist[direct].alist = NULL;
3714 }
3715
3716 return 0;
3717}
3718
3719/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003720static void
paul718e3742002-12-13 20:15:29 +00003721peer_distribute_update (struct access_list *access)
3722{
3723 afi_t afi;
3724 safi_t safi;
3725 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003726 struct listnode *mnode, *mnnode;
3727 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003728 struct bgp *bgp;
3729 struct peer *peer;
3730 struct peer_group *group;
3731 struct bgp_filter *filter;
3732
paul1eb8ef22005-04-07 07:30:20 +00003733 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003734 {
paul1eb8ef22005-04-07 07:30:20 +00003735 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003736 {
3737 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3738 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3739 {
3740 filter = &peer->filter[afi][safi];
3741
3742 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3743 {
3744 if (filter->dlist[direct].name)
3745 filter->dlist[direct].alist =
3746 access_list_lookup (afi, filter->dlist[direct].name);
3747 else
3748 filter->dlist[direct].alist = NULL;
3749 }
3750 }
3751 }
paul1eb8ef22005-04-07 07:30:20 +00003752 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003753 {
3754 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3755 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3756 {
3757 filter = &group->conf->filter[afi][safi];
3758
3759 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3760 {
3761 if (filter->dlist[direct].name)
3762 filter->dlist[direct].alist =
3763 access_list_lookup (afi, filter->dlist[direct].name);
3764 else
3765 filter->dlist[direct].alist = NULL;
3766 }
3767 }
3768 }
3769 }
3770}
3771
3772/* Set prefix list to the peer. */
3773int
3774peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003775 const char *name)
paul718e3742002-12-13 20:15:29 +00003776{
3777 struct bgp_filter *filter;
3778 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003779 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003780
3781 if (! peer->afc[afi][safi])
3782 return BGP_ERR_PEER_INACTIVE;
3783
3784 if (direct != FILTER_IN && direct != FILTER_OUT)
3785 return BGP_ERR_INVALID_VALUE;
3786
3787 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3788 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3789
3790 filter = &peer->filter[afi][safi];
3791
3792 if (filter->dlist[direct].name)
3793 return BGP_ERR_PEER_FILTER_CONFLICT;
3794
3795 if (filter->plist[direct].name)
3796 free (filter->plist[direct].name);
3797 filter->plist[direct].name = strdup (name);
3798 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3799
3800 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3801 return 0;
3802
3803 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003804 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003805 {
3806 filter = &peer->filter[afi][safi];
3807
3808 if (! peer->af_group[afi][safi])
3809 continue;
3810
3811 if (filter->plist[direct].name)
3812 free (filter->plist[direct].name);
3813 filter->plist[direct].name = strdup (name);
3814 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3815 }
3816 return 0;
3817}
3818
3819int
3820peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3821{
3822 struct bgp_filter *filter;
3823 struct bgp_filter *gfilter;
3824 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003825 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003826
3827 if (! peer->afc[afi][safi])
3828 return BGP_ERR_PEER_INACTIVE;
3829
3830 if (direct != FILTER_IN && direct != FILTER_OUT)
3831 return BGP_ERR_INVALID_VALUE;
3832
3833 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3834 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3835
3836 filter = &peer->filter[afi][safi];
3837
3838 /* apply peer-group filter */
3839 if (peer->af_group[afi][safi])
3840 {
3841 gfilter = &peer->group->conf->filter[afi][safi];
3842
3843 if (gfilter->plist[direct].name)
3844 {
3845 if (filter->plist[direct].name)
3846 free (filter->plist[direct].name);
3847 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3848 filter->plist[direct].plist = gfilter->plist[direct].plist;
3849 return 0;
3850 }
3851 }
3852
3853 if (filter->plist[direct].name)
3854 free (filter->plist[direct].name);
3855 filter->plist[direct].name = NULL;
3856 filter->plist[direct].plist = NULL;
3857
3858 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3859 return 0;
3860
3861 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003862 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003863 {
3864 filter = &peer->filter[afi][safi];
3865
3866 if (! peer->af_group[afi][safi])
3867 continue;
3868
3869 if (filter->plist[direct].name)
3870 free (filter->plist[direct].name);
3871 filter->plist[direct].name = NULL;
3872 filter->plist[direct].plist = NULL;
3873 }
3874
3875 return 0;
3876}
3877
3878/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003879static void
paul718e3742002-12-13 20:15:29 +00003880peer_prefix_list_update (struct prefix_list *plist)
3881{
paul1eb8ef22005-04-07 07:30:20 +00003882 struct listnode *mnode, *mnnode;
3883 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003884 struct bgp *bgp;
3885 struct peer *peer;
3886 struct peer_group *group;
3887 struct bgp_filter *filter;
3888 afi_t afi;
3889 safi_t safi;
3890 int direct;
3891
paul1eb8ef22005-04-07 07:30:20 +00003892 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003893 {
paul1eb8ef22005-04-07 07:30:20 +00003894 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003895 {
3896 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3897 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3898 {
3899 filter = &peer->filter[afi][safi];
3900
3901 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3902 {
3903 if (filter->plist[direct].name)
3904 filter->plist[direct].plist =
3905 prefix_list_lookup (afi, filter->plist[direct].name);
3906 else
3907 filter->plist[direct].plist = NULL;
3908 }
3909 }
3910 }
paul1eb8ef22005-04-07 07:30:20 +00003911 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003912 {
3913 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3914 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3915 {
3916 filter = &group->conf->filter[afi][safi];
3917
3918 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3919 {
3920 if (filter->plist[direct].name)
3921 filter->plist[direct].plist =
3922 prefix_list_lookup (afi, filter->plist[direct].name);
3923 else
3924 filter->plist[direct].plist = NULL;
3925 }
3926 }
3927 }
3928 }
3929}
3930
3931int
3932peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003933 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 (direct != FILTER_IN && direct != FILTER_OUT)
3943 return BGP_ERR_INVALID_VALUE;
3944
3945 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3946 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3947
3948 filter = &peer->filter[afi][safi];
3949
3950 if (filter->aslist[direct].name)
3951 free (filter->aslist[direct].name);
3952 filter->aslist[direct].name = strdup (name);
3953 filter->aslist[direct].aslist = as_list_lookup (name);
3954
3955 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3956 return 0;
3957
3958 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003960 {
3961 filter = &peer->filter[afi][safi];
3962
3963 if (! peer->af_group[afi][safi])
3964 continue;
3965
3966 if (filter->aslist[direct].name)
3967 free (filter->aslist[direct].name);
3968 filter->aslist[direct].name = strdup (name);
3969 filter->aslist[direct].aslist = as_list_lookup (name);
3970 }
3971 return 0;
3972}
3973
3974int
3975peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3976{
3977 struct bgp_filter *filter;
3978 struct bgp_filter *gfilter;
3979 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003980 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003981
3982 if (! peer->afc[afi][safi])
3983 return BGP_ERR_PEER_INACTIVE;
3984
hassob5f29602005-05-25 21:00:28 +00003985 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003986 return BGP_ERR_INVALID_VALUE;
3987
hassob5f29602005-05-25 21:00:28 +00003988 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003989 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3990
3991 filter = &peer->filter[afi][safi];
3992
3993 /* apply peer-group filter */
3994 if (peer->af_group[afi][safi])
3995 {
3996 gfilter = &peer->group->conf->filter[afi][safi];
3997
3998 if (gfilter->aslist[direct].name)
3999 {
4000 if (filter->aslist[direct].name)
4001 free (filter->aslist[direct].name);
4002 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4003 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4004 return 0;
4005 }
4006 }
4007
4008 if (filter->aslist[direct].name)
4009 free (filter->aslist[direct].name);
4010 filter->aslist[direct].name = NULL;
4011 filter->aslist[direct].aslist = NULL;
4012
4013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4014 return 0;
4015
4016 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004017 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004018 {
4019 filter = &peer->filter[afi][safi];
4020
4021 if (! peer->af_group[afi][safi])
4022 continue;
4023
4024 if (filter->aslist[direct].name)
4025 free (filter->aslist[direct].name);
4026 filter->aslist[direct].name = NULL;
4027 filter->aslist[direct].aslist = NULL;
4028 }
4029
4030 return 0;
4031}
4032
paul94f2b392005-06-28 12:44:16 +00004033static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004034peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004035{
4036 afi_t afi;
4037 safi_t safi;
4038 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004039 struct listnode *mnode, *mnnode;
4040 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004041 struct bgp *bgp;
4042 struct peer *peer;
4043 struct peer_group *group;
4044 struct bgp_filter *filter;
4045
paul1eb8ef22005-04-07 07:30:20 +00004046 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004047 {
paul1eb8ef22005-04-07 07:30:20 +00004048 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004049 {
4050 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4051 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4052 {
4053 filter = &peer->filter[afi][safi];
4054
4055 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4056 {
4057 if (filter->aslist[direct].name)
4058 filter->aslist[direct].aslist =
4059 as_list_lookup (filter->aslist[direct].name);
4060 else
4061 filter->aslist[direct].aslist = NULL;
4062 }
4063 }
4064 }
paul1eb8ef22005-04-07 07:30:20 +00004065 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004066 {
4067 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4068 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4069 {
4070 filter = &group->conf->filter[afi][safi];
4071
4072 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4073 {
4074 if (filter->aslist[direct].name)
4075 filter->aslist[direct].aslist =
4076 as_list_lookup (filter->aslist[direct].name);
4077 else
4078 filter->aslist[direct].aslist = NULL;
4079 }
4080 }
4081 }
4082 }
4083}
4084
4085/* Set route-map to the peer. */
4086int
4087peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004088 const char *name)
paul718e3742002-12-13 20:15:29 +00004089{
4090 struct bgp_filter *filter;
4091 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004093
4094 if (! peer->afc[afi][safi])
4095 return BGP_ERR_PEER_INACTIVE;
4096
paulfee0f4c2004-09-13 05:12:46 +00004097 if (direct != RMAP_IN && direct != RMAP_OUT &&
4098 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004099 return BGP_ERR_INVALID_VALUE;
4100
paulfee0f4c2004-09-13 05:12:46 +00004101 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4102 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004103 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4104
4105 filter = &peer->filter[afi][safi];
4106
4107 if (filter->map[direct].name)
4108 free (filter->map[direct].name);
4109
4110 filter->map[direct].name = strdup (name);
4111 filter->map[direct].map = route_map_lookup_by_name (name);
4112
4113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4114 return 0;
4115
4116 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004117 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004118 {
4119 filter = &peer->filter[afi][safi];
4120
4121 if (! peer->af_group[afi][safi])
4122 continue;
4123
4124 if (filter->map[direct].name)
4125 free (filter->map[direct].name);
4126 filter->map[direct].name = strdup (name);
4127 filter->map[direct].map = route_map_lookup_by_name (name);
4128 }
4129 return 0;
4130}
4131
4132/* Unset route-map from the peer. */
4133int
4134peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4135{
4136 struct bgp_filter *filter;
4137 struct bgp_filter *gfilter;
4138 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004139 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004140
4141 if (! peer->afc[afi][safi])
4142 return BGP_ERR_PEER_INACTIVE;
4143
hassob5f29602005-05-25 21:00:28 +00004144 if (direct != RMAP_IN && direct != RMAP_OUT &&
4145 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004146 return BGP_ERR_INVALID_VALUE;
4147
hassob5f29602005-05-25 21:00:28 +00004148 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4149 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004150 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4151
4152 filter = &peer->filter[afi][safi];
4153
4154 /* apply peer-group filter */
4155 if (peer->af_group[afi][safi])
4156 {
4157 gfilter = &peer->group->conf->filter[afi][safi];
4158
4159 if (gfilter->map[direct].name)
4160 {
4161 if (filter->map[direct].name)
4162 free (filter->map[direct].name);
4163 filter->map[direct].name = strdup (gfilter->map[direct].name);
4164 filter->map[direct].map = gfilter->map[direct].map;
4165 return 0;
4166 }
4167 }
4168
4169 if (filter->map[direct].name)
4170 free (filter->map[direct].name);
4171 filter->map[direct].name = NULL;
4172 filter->map[direct].map = NULL;
4173
4174 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4175 return 0;
4176
4177 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004178 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004179 {
4180 filter = &peer->filter[afi][safi];
4181
4182 if (! peer->af_group[afi][safi])
4183 continue;
4184
4185 if (filter->map[direct].name)
4186 free (filter->map[direct].name);
4187 filter->map[direct].name = NULL;
4188 filter->map[direct].map = NULL;
4189 }
4190 return 0;
4191}
4192
4193/* Set unsuppress-map to the peer. */
4194int
paulfd79ac92004-10-13 05:06:08 +00004195peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4196 const char *name)
paul718e3742002-12-13 20:15:29 +00004197{
4198 struct bgp_filter *filter;
4199 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004200 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004201
4202 if (! peer->afc[afi][safi])
4203 return BGP_ERR_PEER_INACTIVE;
4204
4205 if (peer_is_group_member (peer, afi, safi))
4206 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4207
4208 filter = &peer->filter[afi][safi];
4209
4210 if (filter->usmap.name)
4211 free (filter->usmap.name);
4212
4213 filter->usmap.name = strdup (name);
4214 filter->usmap.map = route_map_lookup_by_name (name);
4215
4216 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4217 return 0;
4218
4219 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004220 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004221 {
4222 filter = &peer->filter[afi][safi];
4223
4224 if (! peer->af_group[afi][safi])
4225 continue;
4226
4227 if (filter->usmap.name)
4228 free (filter->usmap.name);
4229 filter->usmap.name = strdup (name);
4230 filter->usmap.map = route_map_lookup_by_name (name);
4231 }
4232 return 0;
4233}
4234
4235/* Unset route-map from the peer. */
4236int
4237peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4238{
4239 struct bgp_filter *filter;
4240 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004241 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004242
4243 if (! peer->afc[afi][safi])
4244 return BGP_ERR_PEER_INACTIVE;
4245
4246 if (peer_is_group_member (peer, afi, safi))
4247 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4248
4249 filter = &peer->filter[afi][safi];
4250
4251 if (filter->usmap.name)
4252 free (filter->usmap.name);
4253 filter->usmap.name = NULL;
4254 filter->usmap.map = NULL;
4255
4256 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4257 return 0;
4258
4259 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004260 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004261 {
4262 filter = &peer->filter[afi][safi];
4263
4264 if (! peer->af_group[afi][safi])
4265 continue;
4266
4267 if (filter->usmap.name)
4268 free (filter->usmap.name);
4269 filter->usmap.name = NULL;
4270 filter->usmap.map = NULL;
4271 }
4272 return 0;
4273}
4274
4275int
4276peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004277 u_int32_t max, u_char threshold,
4278 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004279{
4280 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004281 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004282
4283 if (! peer->afc[afi][safi])
4284 return BGP_ERR_PEER_INACTIVE;
4285
4286 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4287 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004288 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004289 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004290 if (warning)
4291 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4292 else
4293 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4294
4295 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4296 return 0;
4297
4298 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004299 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004300 {
4301 if (! peer->af_group[afi][safi])
4302 continue;
4303
4304 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4305 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004306 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004307 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004308 if (warning)
4309 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4310 else
4311 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4312 }
4313 return 0;
4314}
4315
4316int
4317peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4318{
4319 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004320 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004321
4322 if (! peer->afc[afi][safi])
4323 return BGP_ERR_PEER_INACTIVE;
4324
4325 /* apply peer-group config */
4326 if (peer->af_group[afi][safi])
4327 {
4328 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4329 PEER_FLAG_MAX_PREFIX))
4330 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4331 else
4332 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4333
4334 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4335 PEER_FLAG_MAX_PREFIX_WARNING))
4336 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4337 else
4338 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4339
4340 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004341 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004342 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004343 return 0;
4344 }
4345
4346 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4347 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4348 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004349 peer->pmax_threshold[afi][safi] = 0;
4350 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004351
4352 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4353 return 0;
4354
4355 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004356 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004357 {
4358 if (! peer->af_group[afi][safi])
4359 continue;
4360
4361 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4362 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4363 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004364 peer->pmax_threshold[afi][safi] = 0;
4365 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004366 }
4367 return 0;
4368}
4369
Nick Hilliardfa411a22011-03-23 15:33:17 +00004370/* Set # of hops between us and BGP peer. */
4371int
4372peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4373{
4374 struct peer_group *group;
4375 struct listnode *node, *nnode;
4376 struct peer *peer1;
4377 int ret;
4378
4379 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4380
4381 if (peer_sort (peer) == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004382 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004383
4384 /* We cannot configure ttl-security hops when ebgp-multihop is already
4385 set. For non peer-groups, the check is simple. For peer-groups, it's
4386 slightly messy, because we need to check both the peer-group structure
4387 and all peer-group members for any trace of ebgp-multihop configuration
4388 before actually applying the ttl-security rules. Cisco really made a
4389 mess of this configuration parameter, and OpenBGPD got it right.
4390 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004391
4392 if (peer->gtsm_hops == 0) {
4393 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4394 {
4395 group = peer->group;
4396 if (group->conf->ttl != 1)
4397 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004398
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004399 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4400 {
4401 if (peer_sort (peer1) == BGP_PEER_IBGP)
4402 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004403
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004404 if (peer1->ttl != 1)
4405 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4406 }
4407 }
4408 else
4409 {
4410 if (peer->ttl != 1)
4411 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4412 }
4413 /* specify MAXTTL on outgoing packets */
4414 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4415 if (ret != 0)
4416 return ret;
4417 }
4418
Nick Hilliardfa411a22011-03-23 15:33:17 +00004419 peer->gtsm_hops = gtsm_hops;
4420
Nick Hilliardfa411a22011-03-23 15:33:17 +00004421 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4422 {
4423 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4424 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4425 }
4426 else
4427 {
4428 group = peer->group;
4429 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4430 {
4431 if (peer_sort (peer) == BGP_PEER_IBGP)
4432 continue;
4433
4434 peer->gtsm_hops = group->conf->gtsm_hops;
4435
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004436 /* Change setting of existing peer
4437 * established then change value (may break connectivity)
4438 * not established yet (teardown session and restart)
4439 * no session then do nothing (will get handled by next connection)
4440 */
4441 if (peer->status == Established)
4442 {
4443 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4444 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4445 MAXTTL + 1 - peer->gtsm_hops);
4446 }
4447 else if (peer->status < Established)
4448 {
4449 if (BGP_DEBUG (events, EVENTS))
4450 zlog_debug ("%s Min-ttl changed", peer->host);
4451 BGP_EVENT_ADD (peer, BGP_Stop);
4452 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004453 }
4454 }
4455
4456 return 0;
4457}
4458
4459int
4460peer_ttl_security_hops_unset (struct peer *peer)
4461{
4462 struct peer_group *group;
4463 struct listnode *node, *nnode;
4464 struct peer *opeer;
4465
4466 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4467
4468 if (peer_sort (peer) == BGP_PEER_IBGP)
4469 return 0;
4470
4471 /* if a peer-group member, then reset to peer-group default rather than 0 */
4472 if (peer_group_active (peer))
4473 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4474 else
4475 peer->gtsm_hops = 0;
4476
4477 opeer = peer;
4478 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4479 {
4480 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
4481 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4482 }
4483 else
4484 {
4485 group = peer->group;
4486 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4487 {
4488 if (peer_sort (peer) == BGP_PEER_IBGP)
4489 continue;
4490
4491 peer->gtsm_hops = 0;
4492
4493 if (peer->fd >= 0)
4494 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4495 }
4496 }
4497
4498 return peer_ebgp_multihop_unset (opeer);
4499}
4500
paul718e3742002-12-13 20:15:29 +00004501int
4502peer_clear (struct peer *peer)
4503{
4504 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4505 {
hasso0a486e52005-02-01 20:57:17 +00004506 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4507 {
4508 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4509 if (peer->t_pmax_restart)
4510 {
4511 BGP_TIMER_OFF (peer->t_pmax_restart);
4512 if (BGP_DEBUG (events, EVENTS))
4513 zlog_debug ("%s Maximum-prefix restart timer canceled",
4514 peer->host);
4515 }
4516 BGP_EVENT_ADD (peer, BGP_Start);
4517 return 0;
4518 }
4519
paul718e3742002-12-13 20:15:29 +00004520 peer->v_start = BGP_INIT_START_TIMER;
4521 if (peer->status == Established)
4522 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4523 BGP_NOTIFY_CEASE_ADMIN_RESET);
4524 else
4525 BGP_EVENT_ADD (peer, BGP_Stop);
4526 }
4527 return 0;
4528}
4529
4530int
4531peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4532 enum bgp_clear_type stype)
4533{
4534 if (peer->status != Established)
4535 return 0;
4536
4537 if (! peer->afc[afi][safi])
4538 return BGP_ERR_AF_UNCONFIGURED;
4539
paulfee0f4c2004-09-13 05:12:46 +00004540 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4541 {
4542 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4543 return 0;
4544 bgp_check_local_routes_rsclient (peer, afi, safi);
4545 bgp_soft_reconfig_rsclient (peer, afi, safi);
4546 }
4547
paul718e3742002-12-13 20:15:29 +00004548 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4549 bgp_announce_route (peer, afi, safi);
4550
4551 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4552 {
4553 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4554 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4555 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4556 {
4557 struct bgp_filter *filter = &peer->filter[afi][safi];
4558 u_char prefix_type;
4559
4560 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4561 prefix_type = ORF_TYPE_PREFIX;
4562 else
4563 prefix_type = ORF_TYPE_PREFIX_OLD;
4564
4565 if (filter->plist[FILTER_IN].plist)
4566 {
4567 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4568 bgp_route_refresh_send (peer, afi, safi,
4569 prefix_type, REFRESH_DEFER, 1);
4570 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4571 REFRESH_IMMEDIATE, 0);
4572 }
4573 else
4574 {
4575 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4576 bgp_route_refresh_send (peer, afi, safi,
4577 prefix_type, REFRESH_IMMEDIATE, 1);
4578 else
4579 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4580 }
4581 return 0;
4582 }
4583 }
4584
4585 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4586 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4587 {
4588 /* If neighbor has soft reconfiguration inbound flag.
4589 Use Adj-RIB-In database. */
4590 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4591 bgp_soft_reconfig_in (peer, afi, safi);
4592 else
4593 {
4594 /* If neighbor has route refresh capability, send route refresh
4595 message to the peer. */
4596 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4597 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4598 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4599 else
4600 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4601 }
4602 }
4603 return 0;
4604}
4605
paulfd79ac92004-10-13 05:06:08 +00004606/* Display peer uptime.*/
4607/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004608char *
4609peer_uptime (time_t uptime2, char *buf, size_t len)
4610{
4611 time_t uptime1;
4612 struct tm *tm;
4613
4614 /* Check buffer length. */
4615 if (len < BGP_UPTIME_LEN)
4616 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004617 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004618 /* XXX: should return status instead of buf... */
4619 snprintf (buf, len, "<error> ");
4620 return buf;
paul718e3742002-12-13 20:15:29 +00004621 }
4622
4623 /* If there is no connection has been done before print `never'. */
4624 if (uptime2 == 0)
4625 {
4626 snprintf (buf, len, "never ");
4627 return buf;
4628 }
4629
4630 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004631 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004632 uptime1 -= uptime2;
4633 tm = gmtime (&uptime1);
4634
4635 /* Making formatted timer strings. */
4636#define ONE_DAY_SECOND 60*60*24
4637#define ONE_WEEK_SECOND 60*60*24*7
4638
4639 if (uptime1 < ONE_DAY_SECOND)
4640 snprintf (buf, len, "%02d:%02d:%02d",
4641 tm->tm_hour, tm->tm_min, tm->tm_sec);
4642 else if (uptime1 < ONE_WEEK_SECOND)
4643 snprintf (buf, len, "%dd%02dh%02dm",
4644 tm->tm_yday, tm->tm_hour, tm->tm_min);
4645 else
4646 snprintf (buf, len, "%02dw%dd%02dh",
4647 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4648 return buf;
4649}
4650
paul94f2b392005-06-28 12:44:16 +00004651static void
paul718e3742002-12-13 20:15:29 +00004652bgp_config_write_filter (struct vty *vty, struct peer *peer,
4653 afi_t afi, safi_t safi)
4654{
4655 struct bgp_filter *filter;
4656 struct bgp_filter *gfilter = NULL;
4657 char *addr;
4658 int in = FILTER_IN;
4659 int out = FILTER_OUT;
4660
4661 addr = peer->host;
4662 filter = &peer->filter[afi][safi];
4663 if (peer->af_group[afi][safi])
4664 gfilter = &peer->group->conf->filter[afi][safi];
4665
4666 /* distribute-list. */
4667 if (filter->dlist[in].name)
4668 if (! gfilter || ! gfilter->dlist[in].name
4669 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4670 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4671 filter->dlist[in].name, VTY_NEWLINE);
4672 if (filter->dlist[out].name && ! gfilter)
4673 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4674 filter->dlist[out].name, VTY_NEWLINE);
4675
4676 /* prefix-list. */
4677 if (filter->plist[in].name)
4678 if (! gfilter || ! gfilter->plist[in].name
4679 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4680 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4681 filter->plist[in].name, VTY_NEWLINE);
4682 if (filter->plist[out].name && ! gfilter)
4683 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4684 filter->plist[out].name, VTY_NEWLINE);
4685
4686 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004687 if (filter->map[RMAP_IN].name)
4688 if (! gfilter || ! gfilter->map[RMAP_IN].name
4689 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004690 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004691 filter->map[RMAP_IN].name, VTY_NEWLINE);
4692 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004693 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004694 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4695 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4696 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4697 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4698 if (filter->map[RMAP_EXPORT].name)
4699 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4700 || strcmp (filter->map[RMAP_EXPORT].name,
4701 gfilter->map[RMAP_EXPORT].name) != 0)
4702 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4703 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004704
4705 /* unsuppress-map */
4706 if (filter->usmap.name && ! gfilter)
4707 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4708 filter->usmap.name, VTY_NEWLINE);
4709
4710 /* filter-list. */
4711 if (filter->aslist[in].name)
4712 if (! gfilter || ! gfilter->aslist[in].name
4713 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4714 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4715 filter->aslist[in].name, VTY_NEWLINE);
4716 if (filter->aslist[out].name && ! gfilter)
4717 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4718 filter->aslist[out].name, VTY_NEWLINE);
4719}
4720
4721/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004722static void
paul718e3742002-12-13 20:15:29 +00004723bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4724 struct peer *peer, afi_t afi, safi_t safi)
4725{
4726 struct bgp_filter *filter;
4727 struct peer *g_peer = NULL;
4728 char buf[SU_ADDRSTRLEN];
4729 char *addr;
4730
4731 filter = &peer->filter[afi][safi];
4732 addr = peer->host;
4733 if (peer_group_active (peer))
4734 g_peer = peer->group->conf;
4735
4736 /************************************
4737 ****** Global to the neighbor ******
4738 ************************************/
4739 if (afi == AFI_IP && safi == SAFI_UNICAST)
4740 {
4741 /* remote-as. */
4742 if (! peer_group_active (peer))
4743 {
4744 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4745 vty_out (vty, " neighbor %s peer-group%s", addr,
4746 VTY_NEWLINE);
4747 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004748 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004749 VTY_NEWLINE);
4750 }
4751 else
4752 {
4753 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004754 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004755 VTY_NEWLINE);
4756 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4757 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4758 peer->group->name, VTY_NEWLINE);
4759 }
4760
4761 /* local-as. */
4762 if (peer->change_local_as)
4763 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004764 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004765 peer->change_local_as,
4766 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4767 " no-prepend" : "", VTY_NEWLINE);
4768
4769 /* Description. */
4770 if (peer->desc)
4771 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4772 VTY_NEWLINE);
4773
4774 /* Shutdown. */
4775 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4776 if (! peer_group_active (peer) ||
4777 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4778 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4779
Paul Jakma0df7c912008-07-21 21:02:49 +00004780 /* Password. */
4781 if (peer->password)
4782 if (!peer_group_active (peer)
4783 || ! g_peer->password
4784 || strcmp (peer->password, g_peer->password) != 0)
4785 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4786 VTY_NEWLINE);
4787
paul718e3742002-12-13 20:15:29 +00004788 /* BGP port. */
4789 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004790 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004791 VTY_NEWLINE);
4792
4793 /* Local interface name. */
4794 if (peer->ifname)
4795 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4796 VTY_NEWLINE);
4797
4798 /* Passive. */
4799 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4800 if (! peer_group_active (peer) ||
4801 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4802 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4803
4804 /* EBGP multihop. */
Nick Hilliardfa411a22011-03-23 15:33:17 +00004805 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
4806 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004807 if (! peer_group_active (peer) ||
4808 g_peer->ttl != peer->ttl)
4809 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4810 VTY_NEWLINE);
4811
Nick Hilliardfa411a22011-03-23 15:33:17 +00004812 /* ttl-security hops */
4813 if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
4814 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004815 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004816 peer->gtsm_hops, VTY_NEWLINE);
4817
hasso6ffd2072005-02-02 14:50:11 +00004818 /* disable-connected-check. */
4819 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004820 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004821 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4822 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004823
4824 /* Update-source. */
4825 if (peer->update_if)
4826 if (! peer_group_active (peer) || ! g_peer->update_if
4827 || strcmp (g_peer->update_if, peer->update_if) != 0)
4828 vty_out (vty, " neighbor %s update-source %s%s", addr,
4829 peer->update_if, VTY_NEWLINE);
4830 if (peer->update_source)
4831 if (! peer_group_active (peer) || ! g_peer->update_source
4832 || sockunion_cmp (g_peer->update_source,
4833 peer->update_source) != 0)
4834 vty_out (vty, " neighbor %s update-source %s%s", addr,
4835 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4836 VTY_NEWLINE);
4837
paul718e3742002-12-13 20:15:29 +00004838 /* advertisement-interval */
4839 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4840 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4841 addr, peer->v_routeadv, VTY_NEWLINE);
4842
4843 /* timers. */
4844 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4845 && ! peer_group_active (peer))
4846 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4847 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4848
4849 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4850 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4851 peer->connect, VTY_NEWLINE);
4852
4853 /* Default weight. */
4854 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4855 if (! peer_group_active (peer) ||
4856 g_peer->weight != peer->weight)
4857 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4858 VTY_NEWLINE);
4859
paul718e3742002-12-13 20:15:29 +00004860 /* Dynamic capability. */
4861 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4862 if (! peer_group_active (peer) ||
4863 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4864 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4865 VTY_NEWLINE);
4866
4867 /* dont capability negotiation. */
4868 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4869 if (! peer_group_active (peer) ||
4870 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4871 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4872 VTY_NEWLINE);
4873
4874 /* override capability negotiation. */
4875 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4876 if (! peer_group_active (peer) ||
4877 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4878 vty_out (vty, " neighbor %s override-capability%s", addr,
4879 VTY_NEWLINE);
4880
4881 /* strict capability negotiation. */
4882 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4883 if (! peer_group_active (peer) ||
4884 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4885 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4886 VTY_NEWLINE);
4887
4888 if (! peer_group_active (peer))
4889 {
4890 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4891 {
4892 if (peer->afc[AFI_IP][SAFI_UNICAST])
4893 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4894 }
4895 else
4896 {
4897 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4898 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4899 }
4900 }
4901 }
4902
4903
4904 /************************************
4905 ****** Per AF to the neighbor ******
4906 ************************************/
4907
4908 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4909 {
4910 if (peer->af_group[afi][safi])
4911 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4912 peer->group->name, VTY_NEWLINE);
4913 else
4914 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4915 }
4916
4917 /* ORF capability. */
4918 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4919 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4920 if (! peer->af_group[afi][safi])
4921 {
4922 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4923
4924 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4925 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4926 vty_out (vty, " both");
4927 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4928 vty_out (vty, " send");
4929 else
4930 vty_out (vty, " receive");
4931 vty_out (vty, "%s", VTY_NEWLINE);
4932 }
4933
4934 /* Route reflector client. */
4935 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4936 && ! peer->af_group[afi][safi])
4937 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4938 VTY_NEWLINE);
4939
4940 /* Nexthop self. */
4941 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4942 && ! peer->af_group[afi][safi])
4943 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4944
4945 /* Remove private AS. */
4946 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4947 && ! peer->af_group[afi][safi])
4948 vty_out (vty, " neighbor %s remove-private-AS%s",
4949 addr, VTY_NEWLINE);
4950
4951 /* send-community print. */
4952 if (! peer->af_group[afi][safi])
4953 {
4954 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4955 {
4956 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4957 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4958 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4959 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4960 vty_out (vty, " neighbor %s send-community extended%s",
4961 addr, VTY_NEWLINE);
4962 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4963 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4964 }
4965 else
4966 {
4967 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4968 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4969 vty_out (vty, " no neighbor %s send-community both%s",
4970 addr, VTY_NEWLINE);
4971 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4972 vty_out (vty, " no neighbor %s send-community extended%s",
4973 addr, VTY_NEWLINE);
4974 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4975 vty_out (vty, " no neighbor %s send-community%s",
4976 addr, VTY_NEWLINE);
4977 }
4978 }
4979
4980 /* Default information */
4981 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4982 && ! peer->af_group[afi][safi])
4983 {
4984 vty_out (vty, " neighbor %s default-originate", addr);
4985 if (peer->default_rmap[afi][safi].name)
4986 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4987 vty_out (vty, "%s", VTY_NEWLINE);
4988 }
4989
4990 /* Soft reconfiguration inbound. */
4991 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4992 if (! peer->af_group[afi][safi] ||
4993 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4994 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4995 VTY_NEWLINE);
4996
4997 /* maximum-prefix. */
4998 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4999 if (! peer->af_group[afi][safi]
5000 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005001 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005002 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5003 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005004 {
hasso0a486e52005-02-01 20:57:17 +00005005 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5006 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5007 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5008 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5009 vty_out (vty, " warning-only");
5010 if (peer->pmax_restart[afi][safi])
5011 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5012 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005013 }
paul718e3742002-12-13 20:15:29 +00005014
5015 /* Route server client. */
5016 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5017 && ! peer->af_group[afi][safi])
5018 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5019
5020 /* Allow AS in. */
5021 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5022 if (! peer_group_active (peer)
5023 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5024 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5025 {
5026 if (peer->allowas_in[afi][safi] == 3)
5027 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5028 else
5029 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5030 peer->allowas_in[afi][safi], VTY_NEWLINE);
5031 }
5032
5033 /* Filter. */
5034 bgp_config_write_filter (vty, peer, afi, safi);
5035
5036 /* atribute-unchanged. */
5037 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5038 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5039 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5040 && ! peer->af_group[afi][safi])
5041 {
5042 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5043 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5044 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5045 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5046 else
5047 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5048 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5049 " as-path" : "",
5050 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5051 " next-hop" : "",
5052 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5053 " med" : "", VTY_NEWLINE);
5054 }
5055}
5056
5057/* Display "address-family" configuration header. */
5058void
5059bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5060 int *write)
5061{
5062 if (*write)
5063 return;
5064
5065 if (afi == AFI_IP && safi == SAFI_UNICAST)
5066 return;
5067
5068 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5069
5070 if (afi == AFI_IP)
5071 {
5072 if (safi == SAFI_MULTICAST)
5073 vty_out (vty, "ipv4 multicast");
5074 else if (safi == SAFI_MPLS_VPN)
5075 vty_out (vty, "vpnv4 unicast");
5076 }
5077 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005078 {
5079 vty_out (vty, "ipv6");
5080
5081 if (safi == SAFI_MULTICAST)
5082 vty_out (vty, " multicast");
5083 }
paul718e3742002-12-13 20:15:29 +00005084
5085 vty_out (vty, "%s", VTY_NEWLINE);
5086
5087 *write = 1;
5088}
5089
5090/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005091static int
paul718e3742002-12-13 20:15:29 +00005092bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5093 safi_t safi)
5094{
5095 int write = 0;
5096 struct peer *peer;
5097 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005098 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005099
5100 bgp_config_write_network (vty, bgp, afi, safi, &write);
5101
5102 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5103
paul1eb8ef22005-04-07 07:30:20 +00005104 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005105 {
5106 if (group->conf->afc[afi][safi])
5107 {
5108 bgp_config_write_family_header (vty, afi, safi, &write);
5109 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5110 }
5111 }
paul1eb8ef22005-04-07 07:30:20 +00005112 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005113 {
5114 if (peer->afc[afi][safi])
5115 {
5116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5117 {
5118 bgp_config_write_family_header (vty, afi, safi, &write);
5119 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5120 }
5121 }
5122 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005123
5124 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5125
paul718e3742002-12-13 20:15:29 +00005126 if (write)
5127 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5128
5129 return write;
5130}
5131
5132int
5133bgp_config_write (struct vty *vty)
5134{
5135 int write = 0;
5136 struct bgp *bgp;
5137 struct peer_group *group;
5138 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005139 struct listnode *node, *nnode;
5140 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005141
5142 /* BGP Multiple instance. */
5143 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5144 {
5145 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5146 write++;
5147 }
5148
5149 /* BGP Config type. */
5150 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5151 {
5152 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5153 write++;
5154 }
5155
5156 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005157 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005158 {
5159 if (write)
5160 vty_out (vty, "!%s", VTY_NEWLINE);
5161
5162 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005163 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005164
5165 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5166 {
5167 if (bgp->name)
5168 vty_out (vty, " view %s", bgp->name);
5169 }
5170 vty_out (vty, "%s", VTY_NEWLINE);
5171
5172 /* No Synchronization */
5173 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5174 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5175
5176 /* BGP fast-external-failover. */
5177 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5178 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5179
5180 /* BGP router ID. */
5181 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5182 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5183 VTY_NEWLINE);
5184
paul848973c2003-08-13 00:32:49 +00005185 /* BGP log-neighbor-changes. */
5186 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5187 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5188
paul718e3742002-12-13 20:15:29 +00005189 /* BGP configuration. */
5190 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5191 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5192
5193 /* BGP default ipv4-unicast. */
5194 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5195 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5196
5197 /* BGP default local-preference. */
5198 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5199 vty_out (vty, " bgp default local-preference %d%s",
5200 bgp->default_local_pref, VTY_NEWLINE);
5201
5202 /* BGP client-to-client reflection. */
5203 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5204 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5205
5206 /* BGP cluster ID. */
5207 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5208 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5209 VTY_NEWLINE);
5210
hassoe0701b72004-05-20 09:19:34 +00005211 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005212 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005213 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5214 VTY_NEWLINE);
5215
5216 /* Confederation peer */
5217 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005218 {
hassoe0701b72004-05-20 09:19:34 +00005219 int i;
paul718e3742002-12-13 20:15:29 +00005220
hassoe0701b72004-05-20 09:19:34 +00005221 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005222
hassoe0701b72004-05-20 09:19:34 +00005223 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005224 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005225
hassoe0701b72004-05-20 09:19:34 +00005226 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005227 }
5228
5229 /* BGP enforce-first-as. */
5230 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5231 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5232
5233 /* BGP deterministic-med. */
5234 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5235 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005236
5237 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005238 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5239 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5240 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005241 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5242 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5243
paul718e3742002-12-13 20:15:29 +00005244 /* BGP bestpath method. */
5245 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5246 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005247 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5248 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005249 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5250 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5251 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5252 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5253 {
5254 vty_out (vty, " bgp bestpath med");
5255 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5256 vty_out (vty, " confed");
5257 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5258 vty_out (vty, " missing-as-worst");
5259 vty_out (vty, "%s", VTY_NEWLINE);
5260 }
5261
5262 /* BGP network import check. */
5263 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5264 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5265
5266 /* BGP scan interval. */
5267 bgp_config_write_scan_time (vty);
5268
5269 /* BGP flag dampening. */
5270 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5271 BGP_CONFIG_DAMPENING))
5272 bgp_config_write_damp (vty);
5273
5274 /* BGP static route configuration. */
5275 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5276
5277 /* BGP redistribute configuration. */
5278 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5279
5280 /* BGP timers configuration. */
5281 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5282 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5283 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5284 bgp->default_holdtime, VTY_NEWLINE);
5285
5286 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005287 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005288 {
5289 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5290 }
5291
5292 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005293 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005294 {
5295 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5296 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5297 }
5298
Josh Bailey165b5ff2011-07-20 20:43:22 -07005299 /* maximum-paths */
5300 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5301
paul718e3742002-12-13 20:15:29 +00005302 /* Distance configuration. */
5303 bgp_config_write_distance (vty, bgp);
5304
5305 /* No auto-summary */
5306 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5307 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5308
5309 /* IPv4 multicast configuration. */
5310 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5311
5312 /* IPv4 VPN configuration. */
5313 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5314
5315 /* IPv6 unicast configuration. */
5316 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5317
Paul Jakma37a217a2007-04-10 19:20:29 +00005318 /* IPv6 multicast configuration. */
5319 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5320
paul718e3742002-12-13 20:15:29 +00005321 write++;
5322 }
5323 return write;
5324}
5325
5326void
paul94f2b392005-06-28 12:44:16 +00005327bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005328{
5329 memset (&bgp_master, 0, sizeof (struct bgp_master));
5330
5331 bm = &bgp_master;
5332 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005333 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005334 bm->port = BGP_PORT_DEFAULT;
5335 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005336 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005337}
paul200df112005-06-01 11:17:05 +00005338
paul718e3742002-12-13 20:15:29 +00005339
5340void
paul94f2b392005-06-28 12:44:16 +00005341bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005342{
paul718e3742002-12-13 20:15:29 +00005343 /* BGP VTY commands installation. */
5344 bgp_vty_init ();
5345
paul718e3742002-12-13 20:15:29 +00005346 /* Init zebra. */
5347 bgp_zebra_init ();
5348
5349 /* BGP inits. */
5350 bgp_attr_init ();
5351 bgp_debug_init ();
5352 bgp_dump_init ();
5353 bgp_route_init ();
5354 bgp_route_map_init ();
5355 bgp_scan_init ();
5356 bgp_mplsvpn_init ();
5357
5358 /* Access list initialize. */
5359 access_list_init ();
5360 access_list_add_hook (peer_distribute_update);
5361 access_list_delete_hook (peer_distribute_update);
5362
5363 /* Filter list initialize. */
5364 bgp_filter_init ();
5365 as_list_add_hook (peer_aslist_update);
5366 as_list_delete_hook (peer_aslist_update);
5367
5368 /* Prefix list initialize.*/
5369 prefix_list_init ();
5370 prefix_list_add_hook (peer_prefix_list_update);
5371 prefix_list_delete_hook (peer_prefix_list_update);
5372
5373 /* Community list initialize. */
5374 bgp_clist = community_list_init ();
5375
5376#ifdef HAVE_SNMP
5377 bgp_snmp_init ();
5378#endif /* HAVE_SNMP */
5379}
paul545acaf2004-04-20 15:13:15 +00005380
5381void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005382bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005383{
paul545acaf2004-04-20 15:13:15 +00005384 struct bgp *bgp;
5385 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005386 struct listnode *node, *nnode;
5387 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005388
paul1eb8ef22005-04-07 07:30:20 +00005389 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5390 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005391 if (peer->status == Established)
5392 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5393 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005394
paul545acaf2004-04-20 15:13:15 +00005395 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005396
paule210cf92005-06-15 19:15:35 +00005397 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005398 {
5399 work_queue_free (bm->process_main_queue);
5400 bm->process_main_queue = NULL;
5401 }
paule210cf92005-06-15 19:15:35 +00005402 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005403 {
5404 work_queue_free (bm->process_rsclient_queue);
5405 bm->process_rsclient_queue = NULL;
5406 }
paul545acaf2004-04-20 15:13:15 +00005407}