blob: 88d13ed8c1513d579f7cbbc8a2137ddba6a91247 [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:
Paul Jakmacccbc012012-06-14 10:40:26 +010085 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000086 SET_FLAG (bm->options, flag);
87 break;
88 default:
89 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000090 }
91 return 0;
92}
93
94int
95bgp_option_unset (int flag)
96{
97 switch (flag)
98 {
99 case BGP_OPT_MULTIPLE_INSTANCE:
100 if (listcount (bm->bgp) > 1)
101 return BGP_ERR_MULTIPLE_INSTANCE_USED;
102 /* Fall through. */
103 case BGP_OPT_NO_FIB:
104 case BGP_OPT_CONFIG_CISCO:
105 UNSET_FLAG (bm->options, flag);
106 break;
107 default:
108 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000109 }
110 return 0;
111}
112
113int
114bgp_option_check (int flag)
115{
116 return CHECK_FLAG (bm->options, flag);
117}
118
119/* BGP flag manipulation. */
120int
121bgp_flag_set (struct bgp *bgp, int flag)
122{
123 SET_FLAG (bgp->flags, flag);
124 return 0;
125}
126
127int
128bgp_flag_unset (struct bgp *bgp, int flag)
129{
130 UNSET_FLAG (bgp->flags, flag);
131 return 0;
132}
133
134int
135bgp_flag_check (struct bgp *bgp, int flag)
136{
137 return CHECK_FLAG (bgp->flags, flag);
138}
139
140/* Internal function to set BGP structure configureation flag. */
141static void
142bgp_config_set (struct bgp *bgp, int config)
143{
144 SET_FLAG (bgp->config, config);
145}
146
147static void
148bgp_config_unset (struct bgp *bgp, int config)
149{
150 UNSET_FLAG (bgp->config, config);
151}
152
153static int
154bgp_config_check (struct bgp *bgp, int config)
155{
156 return CHECK_FLAG (bgp->config, config);
157}
158
159/* Set BGP router identifier. */
160int
161bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
162{
163 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000165
166 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
167 && IPV4_ADDR_SAME (&bgp->router_id, id))
168 return 0;
169
170 IPV4_ADDR_COPY (&bgp->router_id, id);
171 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
172
173 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000175 {
176 IPV4_ADDR_COPY (&peer->local_id, id);
177
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000178 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000179 {
180 peer->last_reset = PEER_DOWN_RID_CHANGE;
181 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
182 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
183 }
paul718e3742002-12-13 20:15:29 +0000184 }
185 return 0;
186}
187
paul718e3742002-12-13 20:15:29 +0000188/* BGP's cluster-id control. */
189int
190bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
191{
192 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000193 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000194
195 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
196 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
197 return 0;
198
199 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
200 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
201
202 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000204 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000205 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000206 continue;
207
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000208 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000209 {
210 peer->last_reset = PEER_DOWN_CLID_CHANGE;
211 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
212 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
213 }
paul718e3742002-12-13 20:15:29 +0000214 }
215 return 0;
216}
217
218int
219bgp_cluster_id_unset (struct bgp *bgp)
220{
221 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000223
224 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
225 return 0;
226
227 bgp->cluster_id.s_addr = 0;
228 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
229
230 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000231 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000232 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000233 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000234 continue;
235
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000236 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000237 {
238 peer->last_reset = PEER_DOWN_CLID_CHANGE;
239 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
240 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
241 }
paul718e3742002-12-13 20:15:29 +0000242 }
243 return 0;
244}
245
Stephen Hemminger65957882010-01-15 16:22:10 +0300246/* time_t value that is monotonicly increasing
247 * and uneffected by adjustments to system clock
248 */
249time_t bgp_clock (void)
250{
251 struct timeval tv;
252
253 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
254 return tv.tv_sec;
255}
256
paul718e3742002-12-13 20:15:29 +0000257/* BGP timer configuration. */
258int
259bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
260{
261 bgp->default_keepalive = (keepalive < holdtime / 3
262 ? keepalive : holdtime / 3);
263 bgp->default_holdtime = holdtime;
264
265 return 0;
266}
267
268int
269bgp_timers_unset (struct bgp *bgp)
270{
271 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
272 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
273
274 return 0;
275}
276
277/* BGP confederation configuration. */
278int
279bgp_confederation_id_set (struct bgp *bgp, as_t as)
280{
281 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000283 int already_confed;
284
285 if (as == 0)
286 return BGP_ERR_INVALID_AS;
287
288 /* Remember - were we doing confederation before? */
289 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
290 bgp->confed_id = as;
291 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
292
293 /* If we were doing confederation already, this is just an external
294 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
295 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000296 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000297 {
298 /* We're looking for peers who's AS is not local or part of our
299 confederation. */
300 if (already_confed)
301 {
302 if (peer_sort (peer) == BGP_PEER_EBGP)
303 {
304 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000305 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000306 {
307 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
308 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
309 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
310 }
311
paul718e3742002-12-13 20:15:29 +0000312 else
313 BGP_EVENT_ADD (peer, BGP_Stop);
314 }
315 }
316 else
317 {
318 /* Not doign confederation before, so reset every non-local
319 session */
320 if (peer_sort (peer) != BGP_PEER_IBGP)
321 {
322 /* Reset the local_as to be our EBGP one */
323 if (peer_sort (peer) == BGP_PEER_EBGP)
324 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000325 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000326 {
327 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
328 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
329 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
330 }
paul718e3742002-12-13 20:15:29 +0000331 else
332 BGP_EVENT_ADD (peer, BGP_Stop);
333 }
334 }
335 }
336 return 0;
337}
338
339int
340bgp_confederation_id_unset (struct bgp *bgp)
341{
342 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000344
345 bgp->confed_id = 0;
346 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
347
paul1eb8ef22005-04-07 07:30:20 +0000348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000349 {
350 /* We're looking for peers who's AS is not local */
351 if (peer_sort (peer) != BGP_PEER_IBGP)
352 {
353 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000354 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000355 {
356 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
357 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
358 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
359 }
360
paul718e3742002-12-13 20:15:29 +0000361 else
362 BGP_EVENT_ADD (peer, BGP_Stop);
363 }
364 }
365 return 0;
366}
367
368/* Is an AS part of the confed or not? */
369int
370bgp_confederation_peers_check (struct bgp *bgp, as_t as)
371{
372 int i;
373
374 if (! bgp)
375 return 0;
376
377 for (i = 0; i < bgp->confed_peers_cnt; i++)
378 if (bgp->confed_peers[i] == as)
379 return 1;
380
381 return 0;
382}
383
384/* Add an AS to the confederation set. */
385int
386bgp_confederation_peers_add (struct bgp *bgp, as_t as)
387{
388 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000389 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000390
391 if (! bgp)
392 return BGP_ERR_INVALID_BGP;
393
394 if (bgp->as == as)
395 return BGP_ERR_INVALID_AS;
396
397 if (bgp_confederation_peers_check (bgp, as))
398 return -1;
399
400 if (bgp->confed_peers)
401 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
402 bgp->confed_peers,
403 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
404 else
405 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
406 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
407
408 bgp->confed_peers[bgp->confed_peers_cnt] = as;
409 bgp->confed_peers_cnt++;
410
411 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
412 {
paul1eb8ef22005-04-07 07:30:20 +0000413 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000414 {
415 if (peer->as == as)
416 {
417 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000418 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000419 {
420 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
421 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
422 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
423 }
paul718e3742002-12-13 20:15:29 +0000424 else
425 BGP_EVENT_ADD (peer, BGP_Stop);
426 }
427 }
428 }
429 return 0;
430}
431
432/* Delete an AS from the confederation set. */
433int
434bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
435{
436 int i;
437 int j;
438 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000439 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000440
441 if (! bgp)
442 return -1;
443
444 if (! bgp_confederation_peers_check (bgp, as))
445 return -1;
446
447 for (i = 0; i < bgp->confed_peers_cnt; i++)
448 if (bgp->confed_peers[i] == as)
449 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
450 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
451
452 bgp->confed_peers_cnt--;
453
454 if (bgp->confed_peers_cnt == 0)
455 {
456 if (bgp->confed_peers)
457 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
458 bgp->confed_peers = NULL;
459 }
460 else
461 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
462 bgp->confed_peers,
463 bgp->confed_peers_cnt * sizeof (as_t));
464
465 /* Now reset any peer who's remote AS has just been removed from the
466 CONFED */
467 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
468 {
paul1eb8ef22005-04-07 07:30:20 +0000469 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000470 {
471 if (peer->as == as)
472 {
473 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000474 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000475 {
476 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
477 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
478 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
479 }
paul718e3742002-12-13 20:15:29 +0000480 else
481 BGP_EVENT_ADD (peer, BGP_Stop);
482 }
483 }
484 }
485
486 return 0;
487}
488
489/* Local preference configuration. */
490int
491bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
492{
493 if (! bgp)
494 return -1;
495
paul718e3742002-12-13 20:15:29 +0000496 bgp->default_local_pref = local_pref;
497
498 return 0;
499}
500
501int
502bgp_default_local_preference_unset (struct bgp *bgp)
503{
504 if (! bgp)
505 return -1;
506
paul718e3742002-12-13 20:15:29 +0000507 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
508
509 return 0;
510}
511
paulfee0f4c2004-09-13 05:12:46 +0000512/* If peer is RSERVER_CLIENT in at least one address family and is not member
513 of a peer_group for that family, return 1.
514 Used to check wether the peer is included in list bgp->rsclient. */
515int
516peer_rsclient_active (struct peer *peer)
517{
518 int i;
519 int j;
520
521 for (i=AFI_IP; i < AFI_MAX; i++)
522 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
523 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
524 && ! peer->af_group[i][j])
525 return 1;
526 return 0;
527}
528
pauleb821182004-05-01 08:44:08 +0000529/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000530static int
531peer_cmp (struct peer *p1, struct peer *p2)
532{
pauleb821182004-05-01 08:44:08 +0000533 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000534}
535
536int
537peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
538{
539 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
540}
541
542/* Reset all address family specific configuration. */
543static void
544peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
545{
546 int i;
547 struct bgp_filter *filter;
548 char orf_name[BUFSIZ];
549
550 filter = &peer->filter[afi][safi];
551
552 /* Clear neighbor filter and route-map */
553 for (i = FILTER_IN; i < FILTER_MAX; i++)
554 {
555 if (filter->dlist[i].name)
556 {
557 free (filter->dlist[i].name);
558 filter->dlist[i].name = NULL;
559 }
560 if (filter->plist[i].name)
561 {
562 free (filter->plist[i].name);
563 filter->plist[i].name = NULL;
564 }
565 if (filter->aslist[i].name)
566 {
567 free (filter->aslist[i].name);
568 filter->aslist[i].name = NULL;
569 }
paulfee0f4c2004-09-13 05:12:46 +0000570 }
571 for (i = RMAP_IN; i < RMAP_MAX; i++)
572 {
paul718e3742002-12-13 20:15:29 +0000573 if (filter->map[i].name)
574 {
575 free (filter->map[i].name);
576 filter->map[i].name = NULL;
577 }
578 }
579
580 /* Clear unsuppress map. */
581 if (filter->usmap.name)
582 free (filter->usmap.name);
583 filter->usmap.name = NULL;
584 filter->usmap.map = NULL;
585
586 /* Clear neighbor's all address family flags. */
587 peer->af_flags[afi][safi] = 0;
588
589 /* Clear neighbor's all address family sflags. */
590 peer->af_sflags[afi][safi] = 0;
591
592 /* Clear neighbor's all address family capabilities. */
593 peer->af_cap[afi][safi] = 0;
594
595 /* Clear ORF info */
596 peer->orf_plist[afi][safi] = NULL;
597 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
598 prefix_bgp_orf_remove_all (orf_name);
599
600 /* Set default neighbor send-community. */
601 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
602 {
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
605 }
606
607 /* Clear neighbor default_originate_rmap */
608 if (peer->default_rmap[afi][safi].name)
609 free (peer->default_rmap[afi][safi].name);
610 peer->default_rmap[afi][safi].name = NULL;
611 peer->default_rmap[afi][safi].map = NULL;
612
613 /* Clear neighbor maximum-prefix */
614 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000615 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000616}
617
618/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000619static void
paul718e3742002-12-13 20:15:29 +0000620peer_global_config_reset (struct peer *peer)
621{
622 peer->weight = 0;
623 peer->change_local_as = 0;
624 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
625 if (peer->update_source)
626 {
627 sockunion_free (peer->update_source);
628 peer->update_source = NULL;
629 }
630 if (peer->update_if)
631 {
632 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
633 peer->update_if = NULL;
634 }
635
636 if (peer_sort (peer) == BGP_PEER_IBGP)
637 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
638 else
639 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
640
641 peer->flags = 0;
642 peer->config = 0;
643 peer->holdtime = 0;
644 peer->keepalive = 0;
645 peer->connect = 0;
646 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
647}
648
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000649/* Check peer's AS number and determines if this peer is IBGP or EBGP */
650static bgp_peer_sort_t
651peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000652{
653 struct bgp *bgp;
654
655 bgp = peer->bgp;
656
657 /* Peer-group */
658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
659 {
660 if (peer->as)
661 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
662 else
663 {
664 struct peer *peer1;
665 peer1 = listnode_head (peer->group->peer);
666 if (peer1)
667 return (peer1->local_as == peer1->as
668 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
669 }
670 return BGP_PEER_INTERNAL;
671 }
672
673 /* Normal peer */
674 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
675 {
676 if (peer->local_as == 0)
677 return BGP_PEER_INTERNAL;
678
679 if (peer->local_as == peer->as)
680 {
681 if (peer->local_as == bgp->confed_id)
682 return BGP_PEER_EBGP;
683 else
684 return BGP_PEER_IBGP;
685 }
686
687 if (bgp_confederation_peers_check (bgp, peer->as))
688 return BGP_PEER_CONFED;
689
690 return BGP_PEER_EBGP;
691 }
692 else
693 {
694 return (peer->local_as == 0
695 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
696 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
697 }
698}
699
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000700/* Calculate and cache the peer "sort" */
701bgp_peer_sort_t
702peer_sort (struct peer *peer)
703{
704 peer->sort = peer_calc_sort (peer);
705 return peer->sort;
706}
707
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100708static void
paul200df112005-06-01 11:17:05 +0000709peer_free (struct peer *peer)
710{
Paul Jakmaca058a32006-09-14 02:58:49 +0000711 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700712
713 bgp_unlock(peer->bgp);
714
Paul Jakmaca058a32006-09-14 02:58:49 +0000715 /* this /ought/ to have been done already through bgp_stop earlier,
716 * but just to be sure..
717 */
718 bgp_timer_set (peer);
719 BGP_READ_OFF (peer->t_read);
720 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000721 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000722
paul200df112005-06-01 11:17:05 +0000723 if (peer->desc)
724 XFREE (MTYPE_PEER_DESC, peer->desc);
725
726 /* Free allocated host character. */
727 if (peer->host)
728 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
729
730 /* Update source configuration. */
731 if (peer->update_source)
732 sockunion_free (peer->update_source);
733
734 if (peer->update_if)
735 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000736
737 if (peer->clear_node_queue)
738 work_queue_free (peer->clear_node_queue);
739
Paul Jakmaca058a32006-09-14 02:58:49 +0000740 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000741 memset (peer, 0, sizeof (struct peer));
742
743 XFREE (MTYPE_BGP_PEER, peer);
744}
745
746/* increase reference count on a struct peer */
747struct peer *
748peer_lock (struct peer *peer)
749{
750 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000751
paul200df112005-06-01 11:17:05 +0000752 peer->lock++;
753
754 return peer;
755}
756
757/* decrease reference count on a struct peer
758 * struct peer is freed and NULL returned if last reference
759 */
760struct peer *
761peer_unlock (struct peer *peer)
762{
763 assert (peer && (peer->lock > 0));
764
765 peer->lock--;
766
767 if (peer->lock == 0)
768 {
769#if 0
770 zlog_debug ("unlocked and freeing");
771 zlog_backtrace (LOG_DEBUG);
772#endif
773 peer_free (peer);
774 return NULL;
775 }
776
777#if 0
778 if (peer->lock == 1)
779 {
780 zlog_debug ("unlocked to 1");
781 zlog_backtrace (LOG_DEBUG);
782 }
783#endif
784
785 return peer;
786}
787
788/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000789static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000790peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000791{
792 afi_t afi;
793 safi_t safi;
794 struct peer *peer;
795 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000796
797 /* bgp argument is absolutely required */
798 assert (bgp);
799 if (!bgp)
800 return NULL;
801
paul718e3742002-12-13 20:15:29 +0000802 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000803 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000804
805 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000806 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000807 peer->v_start = BGP_INIT_START_TIMER;
808 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
809 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
810 peer->status = Idle;
811 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000812 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000813 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000814 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000815 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700816 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000817
818 /* Set default flags. */
819 for (afi = AFI_IP; afi < AFI_MAX; afi++)
820 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
821 {
822 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
823 {
824 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
825 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
826 }
827 peer->orf_plist[afi][safi] = NULL;
828 }
829 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
830
831 /* Create buffers. */
832 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
833 peer->obuf = stream_fifo_new ();
834 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
835
836 bgp_sync_init (peer);
837
838 /* Get service port number. */
839 sp = getservbyname ("bgp", "tcp");
840 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
841
842 return peer;
843}
844
845/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000846static struct peer *
paul718e3742002-12-13 20:15:29 +0000847peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
848 as_t remote_as, afi_t afi, safi_t safi)
849{
850 int active;
851 struct peer *peer;
852 char buf[SU_ADDRSTRLEN];
853
Paul Jakma6f585442006-10-22 19:13:07 +0000854 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000855 peer->su = *su;
856 peer->local_as = local_as;
857 peer->as = remote_as;
858 peer->local_id = bgp->router_id;
859 peer->v_holdtime = bgp->default_holdtime;
860 peer->v_keepalive = bgp->default_keepalive;
861 if (peer_sort (peer) == BGP_PEER_IBGP)
862 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
863 else
864 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000865
866 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000867 listnode_add_sort (bgp->peer, peer);
868
869 active = peer_active (peer);
870
871 if (afi && safi)
872 peer->afc[afi][safi] = 1;
873
Stephen Hemminger65957882010-01-15 16:22:10 +0300874 /* Last read and reset time set */
875 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000876
paul718e3742002-12-13 20:15:29 +0000877 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000878 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000879
880 /* Make peer's address string. */
881 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000882 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000883
884 /* Set up peer's events and timers. */
885 if (! active && peer_active (peer))
886 bgp_timer_set (peer);
887
888 return peer;
889}
890
pauleb821182004-05-01 08:44:08 +0000891/* Make accept BGP peer. Called from bgp_accept (). */
892struct peer *
893peer_create_accept (struct bgp *bgp)
894{
895 struct peer *peer;
896
Paul Jakma6f585442006-10-22 19:13:07 +0000897 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000898
899 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000900 listnode_add_sort (bgp->peer, peer);
901
902 return peer;
903}
904
paul718e3742002-12-13 20:15:29 +0000905/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000906static void
paul718e3742002-12-13 20:15:29 +0000907peer_as_change (struct peer *peer, as_t as)
908{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000909 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000910
911 /* Stop peer. */
912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
913 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000914 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000915 {
916 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
917 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
918 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
919 }
paul718e3742002-12-13 20:15:29 +0000920 else
921 BGP_EVENT_ADD (peer, BGP_Stop);
922 }
923 type = peer_sort (peer);
924 peer->as = as;
925
paul848973c2003-08-13 00:32:49 +0000926 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
927 && ! bgp_confederation_peers_check (peer->bgp, as)
928 && peer->bgp->as != as)
929 peer->local_as = peer->bgp->confed_id;
930 else
931 peer->local_as = peer->bgp->as;
932
paul718e3742002-12-13 20:15:29 +0000933 /* Advertisement-interval reset */
934 if (peer_sort (peer) == BGP_PEER_IBGP)
935 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
936 else
937 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
938
939 /* TTL reset */
940 if (peer_sort (peer) == BGP_PEER_IBGP)
941 peer->ttl = 255;
942 else if (type == BGP_PEER_IBGP)
943 peer->ttl = 1;
944
945 /* reflector-client reset */
946 if (peer_sort (peer) != BGP_PEER_IBGP)
947 {
948 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
949 PEER_FLAG_REFLECTOR_CLIENT);
950 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
951 PEER_FLAG_REFLECTOR_CLIENT);
952 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
953 PEER_FLAG_REFLECTOR_CLIENT);
954 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
955 PEER_FLAG_REFLECTOR_CLIENT);
956 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
957 PEER_FLAG_REFLECTOR_CLIENT);
958 }
959
960 /* local-as reset */
961 if (peer_sort (peer) != BGP_PEER_EBGP)
962 {
963 peer->change_local_as = 0;
964 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000966 }
967}
968
969/* If peer does not exist, create new one. If peer already exists,
970 set AS number to the peer. */
971int
972peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
973 afi_t afi, safi_t safi)
974{
975 struct peer *peer;
976 as_t local_as;
977
978 peer = peer_lookup (bgp, su);
979
980 if (peer)
981 {
982 /* When this peer is a member of peer-group. */
983 if (peer->group)
984 {
985 if (peer->group->conf->as)
986 {
987 /* Return peer group's AS number. */
988 *as = peer->group->conf->as;
989 return BGP_ERR_PEER_GROUP_MEMBER;
990 }
991 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
992 {
993 if (bgp->as != *as)
994 {
995 *as = peer->as;
996 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
997 }
998 }
999 else
1000 {
1001 if (bgp->as == *as)
1002 {
1003 *as = peer->as;
1004 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1005 }
1006 }
1007 }
1008
1009 /* Existing peer's AS number change. */
1010 if (peer->as != *as)
1011 peer_as_change (peer, *as);
1012 }
1013 else
1014 {
1015
1016 /* If the peer is not part of our confederation, and its not an
1017 iBGP peer then spoof the source AS */
1018 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1019 && ! bgp_confederation_peers_check (bgp, *as)
1020 && bgp->as != *as)
1021 local_as = bgp->confed_id;
1022 else
1023 local_as = bgp->as;
1024
1025 /* If this is IPv4 unicast configuration and "no bgp default
1026 ipv4-unicast" is specified. */
1027
1028 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1029 && afi == AFI_IP && safi == SAFI_UNICAST)
1030 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1031 else
1032 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1033 }
1034
1035 return 0;
1036}
1037
1038/* Activate the peer or peer group for specified AFI and SAFI. */
1039int
1040peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1041{
1042 int active;
1043
1044 if (peer->afc[afi][safi])
1045 return 0;
1046
1047 /* Activate the address family configuration. */
1048 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1049 peer->afc[afi][safi] = 1;
1050 else
1051 {
1052 active = peer_active (peer);
1053
1054 peer->afc[afi][safi] = 1;
1055
1056 if (! active && peer_active (peer))
1057 bgp_timer_set (peer);
1058 else
1059 {
1060 if (peer->status == Established)
1061 {
1062 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1063 {
1064 peer->afc_adv[afi][safi] = 1;
1065 bgp_capability_send (peer, afi, safi,
1066 CAPABILITY_CODE_MP,
1067 CAPABILITY_ACTION_SET);
1068 if (peer->afc_recv[afi][safi])
1069 {
1070 peer->afc_nego[afi][safi] = 1;
1071 bgp_announce_route (peer, afi, safi);
1072 }
1073 }
1074 else
hassoe0701b72004-05-20 09:19:34 +00001075 {
1076 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1077 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1078 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1079 }
paul718e3742002-12-13 20:15:29 +00001080 }
1081 }
1082 }
1083 return 0;
1084}
1085
1086int
1087peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1088{
1089 struct peer_group *group;
1090 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001091 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001092
1093 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1094 {
1095 group = peer->group;
1096
paul1eb8ef22005-04-07 07:30:20 +00001097 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001098 {
1099 if (peer1->af_group[afi][safi])
1100 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1101 }
1102 }
1103 else
1104 {
1105 if (peer->af_group[afi][safi])
1106 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1107 }
1108
1109 if (! peer->afc[afi][safi])
1110 return 0;
1111
1112 /* De-activate the address family configuration. */
1113 peer->afc[afi][safi] = 0;
1114 peer_af_flag_reset (peer, afi, safi);
1115
1116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1117 {
1118 if (peer->status == Established)
1119 {
1120 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1121 {
1122 peer->afc_adv[afi][safi] = 0;
1123 peer->afc_nego[afi][safi] = 0;
1124
1125 if (peer_active_nego (peer))
1126 {
1127 bgp_capability_send (peer, afi, safi,
1128 CAPABILITY_CODE_MP,
1129 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001130 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001131 peer->pcount[afi][safi] = 0;
1132 }
1133 else
hassoe0701b72004-05-20 09:19:34 +00001134 {
1135 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1136 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1137 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1138 }
paul718e3742002-12-13 20:15:29 +00001139 }
1140 else
hassoe0701b72004-05-20 09:19:34 +00001141 {
1142 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1143 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1144 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1145 }
paul718e3742002-12-13 20:15:29 +00001146 }
1147 }
1148 return 0;
1149}
1150
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001151static void
hasso93406d82005-02-02 14:40:33 +00001152peer_nsf_stop (struct peer *peer)
1153{
1154 afi_t afi;
1155 safi_t safi;
1156
1157 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1159
1160 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001161 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001162 peer->nsf[afi][safi] = 0;
1163
1164 if (peer->t_gr_restart)
1165 {
1166 BGP_TIMER_OFF (peer->t_gr_restart);
1167 if (BGP_DEBUG (events, EVENTS))
1168 zlog_debug ("%s graceful restart timer stopped", peer->host);
1169 }
1170 if (peer->t_gr_stale)
1171 {
1172 BGP_TIMER_OFF (peer->t_gr_stale);
1173 if (BGP_DEBUG (events, EVENTS))
1174 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1175 }
1176 bgp_clear_route_all (peer);
1177}
1178
Paul Jakmaca058a32006-09-14 02:58:49 +00001179/* Delete peer from confguration.
1180 *
1181 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1182 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1183 *
1184 * This function /should/ take care to be idempotent, to guard against
1185 * it being called multiple times through stray events that come in
1186 * that happen to result in this function being called again. That
1187 * said, getting here for a "Deleted" peer is a bug in the neighbour
1188 * FSM.
1189 */
paul718e3742002-12-13 20:15:29 +00001190int
1191peer_delete (struct peer *peer)
1192{
1193 int i;
1194 afi_t afi;
1195 safi_t safi;
1196 struct bgp *bgp;
1197 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001198 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001199
Paul Jakmaca058a32006-09-14 02:58:49 +00001200 assert (peer->status != Deleted);
1201
paul718e3742002-12-13 20:15:29 +00001202 bgp = peer->bgp;
1203
hasso93406d82005-02-02 14:40:33 +00001204 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1205 peer_nsf_stop (peer);
1206
Chris Caputo228da422009-07-18 05:44:03 +00001207 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001208 relationship. */
1209 if (peer->group)
1210 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001211 if ((pn = listnode_lookup (peer->group->peer, peer)))
1212 {
1213 peer = peer_unlock (peer); /* group->peer list reference */
1214 list_delete_node (peer->group->peer, pn);
1215 }
paul718e3742002-12-13 20:15:29 +00001216 peer->group = NULL;
1217 }
paul200df112005-06-01 11:17:05 +00001218
paul718e3742002-12-13 20:15:29 +00001219 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001220 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1221 * executed after peer structure is deleted.
1222 */
hassoe0701b72004-05-20 09:19:34 +00001223 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001224 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001225 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001226
1227 /* Password configuration */
1228 if (peer->password)
1229 {
1230 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1231 peer->password = NULL;
1232
1233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1234 bgp_md5_set (peer);
1235 }
1236
Paul Jakmaca058a32006-09-14 02:58:49 +00001237 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001238
paul718e3742002-12-13 20:15:29 +00001239 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1241 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001242 {
Chris Caputo228da422009-07-18 05:44:03 +00001243 peer_unlock (peer); /* bgp peer list reference */
1244 list_delete_node (bgp->peer, pn);
1245 }
paul200df112005-06-01 11:17:05 +00001246
Chris Caputo228da422009-07-18 05:44:03 +00001247 if (peer_rsclient_active (peer)
1248 && (pn = listnode_lookup (bgp->rsclient, peer)))
1249 {
1250 peer_unlock (peer); /* rsclient list reference */
1251 list_delete_node (bgp->rsclient, pn);
1252
1253 /* Clear our own rsclient ribs. */
1254 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1255 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1256 if (CHECK_FLAG(peer->af_flags[afi][safi],
1257 PEER_FLAG_RSERVER_CLIENT))
1258 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001259 }
1260
1261 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1262 member of a peer_group. */
1263 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1264 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1265 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001266 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001267
paul200df112005-06-01 11:17:05 +00001268 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001269 if (peer->ibuf)
1270 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001271 if (peer->obuf)
1272 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001273 if (peer->work)
1274 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001275 peer->obuf = NULL;
1276 peer->work = peer->ibuf = NULL;
1277
paul718e3742002-12-13 20:15:29 +00001278 /* Local and remote addresses. */
1279 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001280 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001281 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001282 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001283 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001284
paul718e3742002-12-13 20:15:29 +00001285 /* Free filter related memory. */
1286 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1287 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1288 {
1289 filter = &peer->filter[afi][safi];
1290
1291 for (i = FILTER_IN; i < FILTER_MAX; i++)
1292 {
1293 if (filter->dlist[i].name)
1294 free (filter->dlist[i].name);
1295 if (filter->plist[i].name)
1296 free (filter->plist[i].name);
1297 if (filter->aslist[i].name)
1298 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001299
1300 filter->dlist[i].name = NULL;
1301 filter->plist[i].name = NULL;
1302 filter->aslist[i].name = NULL;
1303 }
1304 for (i = RMAP_IN; i < RMAP_MAX; i++)
1305 {
paul718e3742002-12-13 20:15:29 +00001306 if (filter->map[i].name)
1307 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001308 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001309 }
1310
1311 if (filter->usmap.name)
1312 free (filter->usmap.name);
1313
1314 if (peer->default_rmap[afi][safi].name)
1315 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001316
1317 filter->usmap.name = NULL;
1318 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001319 }
paul200df112005-06-01 11:17:05 +00001320
1321 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001322
1323 return 0;
1324}
1325
paul94f2b392005-06-28 12:44:16 +00001326static int
paul718e3742002-12-13 20:15:29 +00001327peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1328{
1329 return strcmp (g1->name, g2->name);
1330}
1331
1332/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001333static int
paul718e3742002-12-13 20:15:29 +00001334peer_group_active (struct peer *peer)
1335{
1336 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1337 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1338 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1339 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1340 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1341 return 1;
1342 return 0;
1343}
1344
1345/* Peer group cofiguration. */
1346static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001347peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001348{
1349 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1350 sizeof (struct peer_group));
1351}
1352
paul94f2b392005-06-28 12:44:16 +00001353static void
paul718e3742002-12-13 20:15:29 +00001354peer_group_free (struct peer_group *group)
1355{
1356 XFREE (MTYPE_PEER_GROUP, group);
1357}
1358
1359struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001360peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001361{
1362 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001363 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001364
paul1eb8ef22005-04-07 07:30:20 +00001365 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001366 {
1367 if (strcmp (group->name, name) == 0)
1368 return group;
1369 }
1370 return NULL;
1371}
1372
1373struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001374peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001375{
1376 struct peer_group *group;
1377
1378 group = peer_group_lookup (bgp, name);
1379 if (group)
1380 return group;
1381
1382 group = peer_group_new ();
1383 group->bgp = bgp;
1384 group->name = strdup (name);
1385 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001386 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001387 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1388 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001389 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001390 group->conf->group = group;
1391 group->conf->as = 0;
1392 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001393 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001394 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1395 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1396 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1397 group->conf->keepalive = 0;
1398 group->conf->holdtime = 0;
1399 group->conf->connect = 0;
1400 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1401 listnode_add_sort (bgp->group, group);
1402
1403 return 0;
1404}
1405
paul94f2b392005-06-28 12:44:16 +00001406static void
paul718e3742002-12-13 20:15:29 +00001407peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1408 afi_t afi, safi_t safi)
1409{
1410 int in = FILTER_IN;
1411 int out = FILTER_OUT;
1412 struct peer *conf;
1413 struct bgp_filter *pfilter;
1414 struct bgp_filter *gfilter;
1415
1416 conf = group->conf;
1417 pfilter = &peer->filter[afi][safi];
1418 gfilter = &conf->filter[afi][safi];
1419
1420 /* remote-as */
1421 if (conf->as)
1422 peer->as = conf->as;
1423
1424 /* remote-as */
1425 if (conf->change_local_as)
1426 peer->change_local_as = conf->change_local_as;
1427
1428 /* TTL */
1429 peer->ttl = conf->ttl;
1430
Nick Hilliardfa411a22011-03-23 15:33:17 +00001431 /* GTSM hops */
1432 peer->gtsm_hops = conf->gtsm_hops;
1433
paul718e3742002-12-13 20:15:29 +00001434 /* Weight */
1435 peer->weight = conf->weight;
1436
1437 /* peer flags apply */
1438 peer->flags = conf->flags;
1439 /* peer af_flags apply */
1440 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1441 /* peer config apply */
1442 peer->config = conf->config;
1443
1444 /* peer timers apply */
1445 peer->holdtime = conf->holdtime;
1446 peer->keepalive = conf->keepalive;
1447 peer->connect = conf->connect;
1448 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1449 peer->v_connect = conf->connect;
1450 else
1451 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1452
1453 /* advertisement-interval reset */
1454 if (peer_sort (peer) == BGP_PEER_IBGP)
1455 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1456 else
1457 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1458
Paul Jakma0df7c912008-07-21 21:02:49 +00001459 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001460 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001461 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001462
1463 bgp_md5_set (peer);
1464
paul718e3742002-12-13 20:15:29 +00001465 /* maximum-prefix */
1466 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001467 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001468 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001469
1470 /* allowas-in */
1471 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1472
paulfee0f4c2004-09-13 05:12:46 +00001473 /* route-server-client */
1474 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1475 {
1476 /* Make peer's RIB point to group's RIB. */
1477 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1478
1479 /* Import policy. */
1480 if (pfilter->map[RMAP_IMPORT].name)
1481 free (pfilter->map[RMAP_IMPORT].name);
1482 if (gfilter->map[RMAP_IMPORT].name)
1483 {
1484 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1485 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1486 }
1487 else
1488 {
1489 pfilter->map[RMAP_IMPORT].name = NULL;
1490 pfilter->map[RMAP_IMPORT].map = NULL;
1491 }
1492
1493 /* Export policy. */
1494 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1495 {
1496 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1497 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1498 }
1499 }
1500
paul718e3742002-12-13 20:15:29 +00001501 /* default-originate route-map */
1502 if (conf->default_rmap[afi][safi].name)
1503 {
1504 if (peer->default_rmap[afi][safi].name)
1505 free (peer->default_rmap[afi][safi].name);
1506 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1507 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1508 }
1509
1510 /* update-source apply */
1511 if (conf->update_source)
1512 {
1513 if (peer->update_source)
1514 sockunion_free (peer->update_source);
1515 if (peer->update_if)
1516 {
1517 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1518 peer->update_if = NULL;
1519 }
1520 peer->update_source = sockunion_dup (conf->update_source);
1521 }
1522 else if (conf->update_if)
1523 {
1524 if (peer->update_if)
1525 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1526 if (peer->update_source)
1527 {
1528 sockunion_free (peer->update_source);
1529 peer->update_source = NULL;
1530 }
1531 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1532 }
1533
1534 /* inbound filter apply */
1535 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1536 {
1537 if (pfilter->dlist[in].name)
1538 free (pfilter->dlist[in].name);
1539 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1540 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1541 }
1542 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1543 {
1544 if (pfilter->plist[in].name)
1545 free (pfilter->plist[in].name);
1546 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1547 pfilter->plist[in].plist = gfilter->plist[in].plist;
1548 }
1549 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1550 {
1551 if (pfilter->aslist[in].name)
1552 free (pfilter->aslist[in].name);
1553 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1554 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1555 }
paulfee0f4c2004-09-13 05:12:46 +00001556 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001557 {
paulfee0f4c2004-09-13 05:12:46 +00001558 if (pfilter->map[RMAP_IN].name)
1559 free (pfilter->map[RMAP_IN].name);
1560 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1561 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001562 }
1563
1564 /* outbound filter apply */
1565 if (gfilter->dlist[out].name)
1566 {
1567 if (pfilter->dlist[out].name)
1568 free (pfilter->dlist[out].name);
1569 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1570 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1571 }
1572 else
1573 {
1574 if (pfilter->dlist[out].name)
1575 free (pfilter->dlist[out].name);
1576 pfilter->dlist[out].name = NULL;
1577 pfilter->dlist[out].alist = NULL;
1578 }
1579 if (gfilter->plist[out].name)
1580 {
1581 if (pfilter->plist[out].name)
1582 free (pfilter->plist[out].name);
1583 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1584 pfilter->plist[out].plist = gfilter->plist[out].plist;
1585 }
1586 else
1587 {
1588 if (pfilter->plist[out].name)
1589 free (pfilter->plist[out].name);
1590 pfilter->plist[out].name = NULL;
1591 pfilter->plist[out].plist = NULL;
1592 }
1593 if (gfilter->aslist[out].name)
1594 {
1595 if (pfilter->aslist[out].name)
1596 free (pfilter->aslist[out].name);
1597 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1598 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1599 }
1600 else
1601 {
1602 if (pfilter->aslist[out].name)
1603 free (pfilter->aslist[out].name);
1604 pfilter->aslist[out].name = NULL;
1605 pfilter->aslist[out].aslist = NULL;
1606 }
paulfee0f4c2004-09-13 05:12:46 +00001607 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001608 {
paulfee0f4c2004-09-13 05:12:46 +00001609 if (pfilter->map[RMAP_OUT].name)
1610 free (pfilter->map[RMAP_OUT].name);
1611 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1612 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001613 }
1614 else
1615 {
paulfee0f4c2004-09-13 05:12:46 +00001616 if (pfilter->map[RMAP_OUT].name)
1617 free (pfilter->map[RMAP_OUT].name);
1618 pfilter->map[RMAP_OUT].name = NULL;
1619 pfilter->map[RMAP_OUT].map = NULL;
1620 }
1621
1622 /* RS-client's import/export route-maps. */
1623 if (gfilter->map[RMAP_IMPORT].name)
1624 {
1625 if (pfilter->map[RMAP_IMPORT].name)
1626 free (pfilter->map[RMAP_IMPORT].name);
1627 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1628 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1629 }
1630 else
1631 {
1632 if (pfilter->map[RMAP_IMPORT].name)
1633 free (pfilter->map[RMAP_IMPORT].name);
1634 pfilter->map[RMAP_IMPORT].name = NULL;
1635 pfilter->map[RMAP_IMPORT].map = NULL;
1636 }
1637 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1638 {
1639 if (pfilter->map[RMAP_EXPORT].name)
1640 free (pfilter->map[RMAP_EXPORT].name);
1641 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1642 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001643 }
1644
1645 if (gfilter->usmap.name)
1646 {
1647 if (pfilter->usmap.name)
1648 free (pfilter->usmap.name);
1649 pfilter->usmap.name = strdup (gfilter->usmap.name);
1650 pfilter->usmap.map = gfilter->usmap.map;
1651 }
1652 else
1653 {
1654 if (pfilter->usmap.name)
1655 free (pfilter->usmap.name);
1656 pfilter->usmap.name = NULL;
1657 pfilter->usmap.map = NULL;
1658 }
1659}
1660
1661/* Peer group's remote AS configuration. */
1662int
paulfd79ac92004-10-13 05:06:08 +00001663peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001664{
1665 struct peer_group *group;
1666 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001667 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001668
1669 group = peer_group_lookup (bgp, group_name);
1670 if (! group)
1671 return -1;
1672
1673 if (group->conf->as == *as)
1674 return 0;
1675
1676 /* When we setup peer-group AS number all peer group member's AS
1677 number must be updated to same number. */
1678 peer_as_change (group->conf, *as);
1679
paul1eb8ef22005-04-07 07:30:20 +00001680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001681 {
1682 if (peer->as != *as)
1683 peer_as_change (peer, *as);
1684 }
1685
1686 return 0;
1687}
1688
1689int
1690peer_group_delete (struct peer_group *group)
1691{
1692 struct bgp *bgp;
1693 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001694 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001695
1696 bgp = group->bgp;
1697
paul1eb8ef22005-04-07 07:30:20 +00001698 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001699 {
1700 peer->group = NULL;
1701 peer_delete (peer);
1702 }
1703 list_delete (group->peer);
1704
1705 free (group->name);
1706 group->name = NULL;
1707
1708 group->conf->group = NULL;
1709 peer_delete (group->conf);
1710
1711 /* Delete from all peer_group list. */
1712 listnode_delete (bgp->group, group);
1713
1714 peer_group_free (group);
1715
1716 return 0;
1717}
1718
1719int
1720peer_group_remote_as_delete (struct peer_group *group)
1721{
1722 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001723 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001724
1725 if (! group->conf->as)
1726 return 0;
1727
paul1eb8ef22005-04-07 07:30:20 +00001728 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001729 {
1730 peer->group = NULL;
1731 peer_delete (peer);
1732 }
1733 list_delete_all_node (group->peer);
1734
1735 group->conf->as = 0;
1736
1737 return 0;
1738}
1739
1740/* Bind specified peer to peer group. */
1741int
1742peer_group_bind (struct bgp *bgp, union sockunion *su,
1743 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1744{
1745 struct peer *peer;
1746 int first_member = 0;
1747
1748 /* Check peer group's address family. */
1749 if (! group->conf->afc[afi][safi])
1750 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1751
1752 /* Lookup the peer. */
1753 peer = peer_lookup (bgp, su);
1754
1755 /* Create a new peer. */
1756 if (! peer)
1757 {
1758 if (! group->conf->as)
1759 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1760
1761 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1762 peer->group = group;
1763 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001764
Paul Jakmaca058a32006-09-14 02:58:49 +00001765 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001766 listnode_add (group->peer, peer);
1767 peer_group2peer_config_copy (group, peer, afi, safi);
1768
1769 return 0;
1770 }
1771
1772 /* When the peer already belongs to peer group, check the consistency. */
1773 if (peer->af_group[afi][safi])
1774 {
1775 if (strcmp (peer->group->name, group->name) != 0)
1776 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1777
1778 return 0;
1779 }
1780
1781 /* Check current peer group configuration. */
1782 if (peer_group_active (peer)
1783 && strcmp (peer->group->name, group->name) != 0)
1784 return BGP_ERR_PEER_GROUP_MISMATCH;
1785
1786 if (! group->conf->as)
1787 {
1788 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1789 && peer_sort (group->conf) != peer_sort (peer))
1790 {
1791 if (as)
1792 *as = peer->as;
1793 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1794 }
1795
1796 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1797 first_member = 1;
1798 }
1799
1800 peer->af_group[afi][safi] = 1;
1801 peer->afc[afi][safi] = 1;
1802 if (! peer->group)
1803 {
1804 peer->group = group;
paul200df112005-06-01 11:17:05 +00001805
Paul Jakmaca058a32006-09-14 02:58:49 +00001806 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001807 listnode_add (group->peer, peer);
1808 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 else
1810 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001811
1812 if (first_member)
1813 {
1814 /* Advertisement-interval reset */
1815 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1816 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1817 else
1818 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1819
1820 /* ebgp-multihop reset */
1821 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1822 group->conf->ttl = 255;
1823
1824 /* local-as reset */
1825 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1826 {
1827 group->conf->change_local_as = 0;
1828 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001829 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001830 }
1831 }
paulfee0f4c2004-09-13 05:12:46 +00001832
1833 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1834 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001835 struct listnode *pn;
1836
paulfee0f4c2004-09-13 05:12:46 +00001837 /* If it's not configured as RSERVER_CLIENT in any other address
1838 family, without being member of a peer_group, remove it from
1839 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001840 if (! peer_rsclient_active (peer)
1841 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001842 {
1843 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001844 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001845
1846 /* Clear our own rsclient rib for this afi/safi. */
1847 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001848 }
paulfee0f4c2004-09-13 05:12:46 +00001849
Paul Jakmab608d5b2008-07-02 02:12:07 +00001850 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001851
1852 /* Import policy. */
1853 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1854 {
1855 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1856 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1857 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1858 }
1859
1860 /* Export policy. */
1861 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1862 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1863 {
1864 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1865 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1866 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1867 }
1868 }
1869
paul718e3742002-12-13 20:15:29 +00001870 peer_group2peer_config_copy (group, peer, afi, safi);
1871
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001872 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001873 {
1874 peer->last_reset = PEER_DOWN_RMAP_BIND;
1875 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1876 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1877 }
paul718e3742002-12-13 20:15:29 +00001878 else
1879 BGP_EVENT_ADD (peer, BGP_Stop);
1880
1881 return 0;
1882}
1883
1884int
1885peer_group_unbind (struct bgp *bgp, struct peer *peer,
1886 struct peer_group *group, afi_t afi, safi_t safi)
1887{
1888 if (! peer->af_group[afi][safi])
1889 return 0;
1890
1891 if (group != peer->group)
1892 return BGP_ERR_PEER_GROUP_MISMATCH;
1893
1894 peer->af_group[afi][safi] = 0;
1895 peer->afc[afi][safi] = 0;
1896 peer_af_flag_reset (peer, afi, safi);
1897
paulfee0f4c2004-09-13 05:12:46 +00001898 if (peer->rib[afi][safi])
1899 peer->rib[afi][safi] = NULL;
1900
paul718e3742002-12-13 20:15:29 +00001901 if (! peer_group_active (peer))
1902 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001903 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001904 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001905 listnode_delete (group->peer, peer);
1906 peer->group = NULL;
1907 if (group->conf->as)
1908 {
1909 peer_delete (peer);
1910 return 0;
1911 }
1912 peer_global_config_reset (peer);
1913 }
1914
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001915 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001916 {
1917 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1920 }
paul718e3742002-12-13 20:15:29 +00001921 else
1922 BGP_EVENT_ADD (peer, BGP_Stop);
1923
1924 return 0;
1925}
1926
1927/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001928static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001929bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001930{
1931 struct bgp *bgp;
1932 afi_t afi;
1933 safi_t safi;
1934
paul200df112005-06-01 11:17:05 +00001935 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1936 return NULL;
1937
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001938 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001939 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001940 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001941
1942 bgp->peer = list_new ();
1943 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1944
1945 bgp->group = list_new ();
1946 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1947
paulfee0f4c2004-09-13 05:12:46 +00001948 bgp->rsclient = list_new ();
1949 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1950
paul718e3742002-12-13 20:15:29 +00001951 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1952 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1953 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001954 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1955 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1956 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001957 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1958 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001959 }
1960
1961 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1962 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1963 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001964 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1965 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001966
1967 bgp->as = *as;
1968
1969 if (name)
1970 bgp->name = strdup (name);
1971
1972 return bgp;
1973}
1974
1975/* Return first entry of BGP. */
1976struct bgp *
paul94f2b392005-06-28 12:44:16 +00001977bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001978{
1979 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001980 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001981 return NULL;
1982}
1983
1984/* Lookup BGP entry. */
1985struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001986bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001987{
1988 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001989 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001990
paul1eb8ef22005-04-07 07:30:20 +00001991 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001992 if (bgp->as == as
1993 && ((bgp->name == NULL && name == NULL)
1994 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1995 return bgp;
1996 return NULL;
1997}
1998
1999/* Lookup BGP structure by view name. */
2000struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002001bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002002{
2003 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002005
paul1eb8ef22005-04-07 07:30:20 +00002006 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002007 if ((bgp->name == NULL && name == NULL)
2008 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2009 return bgp;
2010 return NULL;
2011}
2012
2013/* Called from VTY commands. */
2014int
paulfd79ac92004-10-13 05:06:08 +00002015bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002016{
2017 struct bgp *bgp;
2018
2019 /* Multiple instance check. */
2020 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2021 {
2022 if (name)
2023 bgp = bgp_lookup_by_name (name);
2024 else
2025 bgp = bgp_get_default ();
2026
2027 /* Already exists. */
2028 if (bgp)
2029 {
2030 if (bgp->as != *as)
2031 {
2032 *as = bgp->as;
2033 return BGP_ERR_INSTANCE_MISMATCH;
2034 }
2035 *bgp_val = bgp;
2036 return 0;
2037 }
2038 }
2039 else
2040 {
2041 /* BGP instance name can not be specified for single instance. */
2042 if (name)
2043 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2044
2045 /* Get default BGP structure if exists. */
2046 bgp = bgp_get_default ();
2047
2048 if (bgp)
2049 {
2050 if (bgp->as != *as)
2051 {
2052 *as = bgp->as;
2053 return BGP_ERR_AS_MISMATCH;
2054 }
2055 *bgp_val = bgp;
2056 return 0;
2057 }
2058 }
2059
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002060 bgp = bgp_create (as, name);
2061 bgp_router_id_set(bgp, &router_id_zebra);
2062 *bgp_val = bgp;
2063
Paul Jakmaad12dde2012-06-13 22:50:07 +01002064 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002065 if (list_isempty(bm->bgp)
2066 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002067 {
2068 if (bgp_socket (bm->port, bm->address) < 0)
2069 return BGP_ERR_INVALID_VALUE;
2070 }
2071
paul718e3742002-12-13 20:15:29 +00002072 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002073
2074 return 0;
2075}
2076
2077/* Delete BGP instance. */
2078int
2079bgp_delete (struct bgp *bgp)
2080{
2081 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002082 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002083 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002084 struct listnode *next;
2085 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002086 int i;
2087
2088 /* Delete static route. */
2089 bgp_static_delete (bgp);
2090
2091 /* Unset redistribution. */
2092 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2093 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2094 if (i != ZEBRA_ROUTE_BGP)
2095 bgp_redistribute_unset (bgp, afi, i);
2096
paul1eb8ef22005-04-07 07:30:20 +00002097 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002098 {
2099 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2100 {
2101 /* Send notify to remote peer. */
2102 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2103 }
2104
2105 peer_delete (peer);
2106 }
paul718e3742002-12-13 20:15:29 +00002107
Chris Caputo228da422009-07-18 05:44:03 +00002108 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002109 {
2110 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2111 {
2112 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2113 {
2114 /* Send notify to remote peer. */
2115 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2116 }
2117 }
2118 peer_group_delete (group);
2119 }
Chris Caputo228da422009-07-18 05:44:03 +00002120
2121 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002122
2123 if (bgp->peer_self) {
2124 peer_delete(bgp->peer_self);
2125 bgp->peer_self = NULL;
2126 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002127
2128 /* Remove visibility via the master list - there may however still be
2129 * routes to be processed still referencing the struct bgp.
2130 */
2131 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002132 if (list_isempty(bm->bgp))
2133 bgp_close ();
2134
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002135 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002136
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002137 return 0;
2138}
2139
2140static void bgp_free (struct bgp *);
2141
2142void
2143bgp_lock (struct bgp *bgp)
2144{
2145 ++bgp->lock;
2146}
2147
2148void
2149bgp_unlock(struct bgp *bgp)
2150{
Chris Caputo228da422009-07-18 05:44:03 +00002151 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002152 if (--bgp->lock == 0)
2153 bgp_free (bgp);
2154}
2155
2156static void
2157bgp_free (struct bgp *bgp)
2158{
2159 afi_t afi;
2160 safi_t safi;
2161
2162 list_delete (bgp->group);
2163 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002164 list_delete (bgp->rsclient);
2165
paul718e3742002-12-13 20:15:29 +00002166 if (bgp->name)
2167 free (bgp->name);
2168
2169 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2170 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2171 {
2172 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002173 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002174 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002175 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002176 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002177 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002178 }
2179 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002180}
2181
2182struct peer *
2183peer_lookup (struct bgp *bgp, union sockunion *su)
2184{
2185 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002186 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002187
Steve Hillfc4dc592009-07-28 17:54:35 +01002188 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002189 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002190 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2191 if (sockunion_same (&peer->su, su)
2192 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2193 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002194 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002195 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002196 {
2197 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002198
Paul Jakma2158ad22009-07-28 18:10:55 +01002199 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2200 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2201 if (sockunion_same (&peer->su, su)
2202 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2203 return peer;
paul718e3742002-12-13 20:15:29 +00002204 }
2205 return NULL;
2206}
2207
2208struct peer *
2209peer_lookup_with_open (union sockunion *su, as_t remote_as,
2210 struct in_addr *remote_id, int *as)
2211{
2212 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002213 struct listnode *node;
2214 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002215 struct bgp *bgp;
2216
Steve Hillfc4dc592009-07-28 17:54:35 +01002217 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002218 return NULL;
2219
Paul Jakma9d878772009-08-05 16:25:16 +01002220 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002221 {
Paul Jakma9d878772009-08-05 16:25:16 +01002222 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2223 {
2224 if (sockunion_same (&peer->su, su)
2225 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2226 {
2227 if (peer->as == remote_as
2228 && peer->remote_id.s_addr == remote_id->s_addr)
2229 return peer;
2230 if (peer->as == remote_as)
2231 *as = 1;
2232 }
2233 }
2234
2235 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2236 {
2237 if (sockunion_same (&peer->su, su)
2238 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2239 {
2240 if (peer->as == remote_as
2241 && peer->remote_id.s_addr == 0)
2242 return peer;
2243 if (peer->as == remote_as)
2244 *as = 1;
2245 }
2246 }
paul718e3742002-12-13 20:15:29 +00002247 }
2248 return NULL;
2249}
2250
2251/* If peer is configured at least one address family return 1. */
2252int
2253peer_active (struct peer *peer)
2254{
2255 if (peer->afc[AFI_IP][SAFI_UNICAST]
2256 || peer->afc[AFI_IP][SAFI_MULTICAST]
2257 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2258 || peer->afc[AFI_IP6][SAFI_UNICAST]
2259 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2260 return 1;
2261 return 0;
2262}
2263
2264/* If peer is negotiated at least one address family return 1. */
2265int
2266peer_active_nego (struct peer *peer)
2267{
2268 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2269 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2270 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2271 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2272 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2273 return 1;
2274 return 0;
2275}
2276
2277/* peer_flag_change_type. */
2278enum peer_change_type
2279{
2280 peer_change_none,
2281 peer_change_reset,
2282 peer_change_reset_in,
2283 peer_change_reset_out,
2284};
2285
paul94f2b392005-06-28 12:44:16 +00002286static void
paul718e3742002-12-13 20:15:29 +00002287peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2288 enum peer_change_type type)
2289{
2290 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2291 return;
2292
2293 if (type == peer_change_reset)
2294 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2295 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2296 else if (type == peer_change_reset_in)
2297 {
2298 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2299 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2300 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2301 else
2302 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2303 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2304 }
2305 else if (type == peer_change_reset_out)
2306 bgp_announce_route (peer, afi, safi);
2307}
2308
2309struct peer_flag_action
2310{
2311 /* Peer's flag. */
2312 u_int32_t flag;
2313
2314 /* This flag can be set for peer-group member. */
2315 u_char not_for_member;
2316
2317 /* Action when the flag is changed. */
2318 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002319
2320 /* Peer down cause */
2321 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002322};
2323
Stephen Hemminger03621952009-07-21 16:27:20 -07002324static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002325 {
2326 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2327 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2328 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2329 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2330 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002331 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002332 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002333 { 0, 0, 0 }
2334 };
2335
Stephen Hemminger03621952009-07-21 16:27:20 -07002336static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002337 {
2338 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2339 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2340 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2341 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2342 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2343 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2344 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2345 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2346 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2347 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2348 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2349 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2350 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002351 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002352 { 0, 0, 0 }
2353 };
2354
2355/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002356static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002357peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002358 struct peer_flag_action *action, u_int32_t flag)
2359{
2360 int i;
2361 int found = 0;
2362 int reset_in = 0;
2363 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002364 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002365
2366 /* Check peer's frag action. */
2367 for (i = 0; i < size; i++)
2368 {
2369 match = &action_list[i];
2370
2371 if (match->flag == 0)
2372 break;
2373
2374 if (match->flag & flag)
2375 {
2376 found = 1;
2377
2378 if (match->type == peer_change_reset_in)
2379 reset_in = 1;
2380 if (match->type == peer_change_reset_out)
2381 reset_out = 1;
2382 if (match->type == peer_change_reset)
2383 {
2384 reset_in = 1;
2385 reset_out = 1;
2386 }
2387 if (match->not_for_member)
2388 action->not_for_member = 1;
2389 }
2390 }
2391
2392 /* Set peer clear type. */
2393 if (reset_in && reset_out)
2394 action->type = peer_change_reset;
2395 else if (reset_in)
2396 action->type = peer_change_reset_in;
2397 else if (reset_out)
2398 action->type = peer_change_reset_out;
2399 else
2400 action->type = peer_change_none;
2401
2402 return found;
2403}
2404
paul94f2b392005-06-28 12:44:16 +00002405static void
paul718e3742002-12-13 20:15:29 +00002406peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2407{
2408 if (flag == PEER_FLAG_SHUTDOWN)
2409 {
2410 if (CHECK_FLAG (peer->flags, flag))
2411 {
hasso93406d82005-02-02 14:40:33 +00002412 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2413 peer_nsf_stop (peer);
2414
hasso0a486e52005-02-01 20:57:17 +00002415 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2416 if (peer->t_pmax_restart)
2417 {
2418 BGP_TIMER_OFF (peer->t_pmax_restart);
2419 if (BGP_DEBUG (events, EVENTS))
2420 zlog_debug ("%s Maximum-prefix restart timer canceled",
2421 peer->host);
2422 }
2423
hasso93406d82005-02-02 14:40:33 +00002424 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2425 peer_nsf_stop (peer);
2426
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002427 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002428 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2429 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2430 else
2431 BGP_EVENT_ADD (peer, BGP_Stop);
2432 }
2433 else
2434 {
2435 peer->v_start = BGP_INIT_START_TIMER;
2436 BGP_EVENT_ADD (peer, BGP_Stop);
2437 }
2438 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002439 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002440 {
hassoc9502432005-02-01 22:01:48 +00002441 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2442 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2443 else if (flag == PEER_FLAG_PASSIVE)
2444 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002445 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002446 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002447
hassoc9502432005-02-01 22:01:48 +00002448 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2449 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002450 }
2451 else
2452 BGP_EVENT_ADD (peer, BGP_Stop);
2453}
2454
2455/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002456static int
paul718e3742002-12-13 20:15:29 +00002457peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2458{
2459 int found;
2460 int size;
2461 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002462 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002463 struct peer_flag_action action;
2464
2465 memset (&action, 0, sizeof (struct peer_flag_action));
2466 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2467
2468 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2469
2470 /* No flag action is found. */
2471 if (! found)
2472 return BGP_ERR_INVALID_FLAG;
2473
2474 /* Not for peer-group member. */
2475 if (action.not_for_member && peer_group_active (peer))
2476 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2477
2478 /* When unset the peer-group member's flag we have to check
2479 peer-group configuration. */
2480 if (! set && peer_group_active (peer))
2481 if (CHECK_FLAG (peer->group->conf->flags, flag))
2482 {
2483 if (flag == PEER_FLAG_SHUTDOWN)
2484 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2485 else
2486 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2487 }
2488
2489 /* Flag conflict check. */
2490 if (set
2491 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2492 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2493 return BGP_ERR_PEER_FLAG_CONFLICT;
2494
2495 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2496 {
2497 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2498 return 0;
2499 if (! set && ! CHECK_FLAG (peer->flags, flag))
2500 return 0;
2501 }
2502
2503 if (set)
2504 SET_FLAG (peer->flags, flag);
2505 else
2506 UNSET_FLAG (peer->flags, flag);
2507
2508 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2509 {
2510 if (action.type == peer_change_reset)
2511 peer_flag_modify_action (peer, flag);
2512
2513 return 0;
2514 }
2515
2516 /* peer-group member updates. */
2517 group = peer->group;
2518
paul1eb8ef22005-04-07 07:30:20 +00002519 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002520 {
2521 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2522 continue;
2523
2524 if (! set && ! CHECK_FLAG (peer->flags, flag))
2525 continue;
2526
2527 if (set)
2528 SET_FLAG (peer->flags, flag);
2529 else
2530 UNSET_FLAG (peer->flags, flag);
2531
2532 if (action.type == peer_change_reset)
2533 peer_flag_modify_action (peer, flag);
2534 }
2535 return 0;
2536}
2537
2538int
2539peer_flag_set (struct peer *peer, u_int32_t flag)
2540{
2541 return peer_flag_modify (peer, flag, 1);
2542}
2543
2544int
2545peer_flag_unset (struct peer *peer, u_int32_t flag)
2546{
2547 return peer_flag_modify (peer, flag, 0);
2548}
2549
paul94f2b392005-06-28 12:44:16 +00002550static int
paul718e3742002-12-13 20:15:29 +00002551peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2552{
2553 if (peer->af_group[afi][safi])
2554 return 1;
2555 return 0;
2556}
2557
paul94f2b392005-06-28 12:44:16 +00002558static int
paul718e3742002-12-13 20:15:29 +00002559peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2560 int set)
2561{
2562 int found;
2563 int size;
paul1eb8ef22005-04-07 07:30:20 +00002564 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002565 struct peer_group *group;
2566 struct peer_flag_action action;
2567
2568 memset (&action, 0, sizeof (struct peer_flag_action));
2569 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2570
2571 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2572
2573 /* No flag action is found. */
2574 if (! found)
2575 return BGP_ERR_INVALID_FLAG;
2576
2577 /* Adress family must be activated. */
2578 if (! peer->afc[afi][safi])
2579 return BGP_ERR_PEER_INACTIVE;
2580
2581 /* Not for peer-group member. */
2582 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2583 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2584
2585 /* Spcecial check for reflector client. */
2586 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2587 && peer_sort (peer) != BGP_PEER_IBGP)
2588 return BGP_ERR_NOT_INTERNAL_PEER;
2589
2590 /* Spcecial check for remove-private-AS. */
2591 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2592 && peer_sort (peer) == BGP_PEER_IBGP)
2593 return BGP_ERR_REMOVE_PRIVATE_AS;
2594
2595 /* When unset the peer-group member's flag we have to check
2596 peer-group configuration. */
2597 if (! set && peer->af_group[afi][safi])
2598 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2599 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2600
2601 /* When current flag configuration is same as requested one. */
2602 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2603 {
2604 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2605 return 0;
2606 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2607 return 0;
2608 }
2609
2610 if (set)
2611 SET_FLAG (peer->af_flags[afi][safi], flag);
2612 else
2613 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2614
2615 /* Execute action when peer is established. */
2616 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2617 && peer->status == Established)
2618 {
2619 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2620 bgp_clear_adj_in (peer, afi, safi);
2621 else
hassoe0701b72004-05-20 09:19:34 +00002622 {
2623 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2624 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2625 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2626 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2627 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2628 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2629 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2630 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2631
2632 peer_change_action (peer, afi, safi, action.type);
2633 }
2634
paul718e3742002-12-13 20:15:29 +00002635 }
2636
2637 /* Peer group member updates. */
2638 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2639 {
2640 group = peer->group;
2641
paul1eb8ef22005-04-07 07:30:20 +00002642 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002643 {
2644 if (! peer->af_group[afi][safi])
2645 continue;
2646
2647 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2648 continue;
2649
2650 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2651 continue;
2652
2653 if (set)
2654 SET_FLAG (peer->af_flags[afi][safi], flag);
2655 else
2656 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2657
2658 if (peer->status == Established)
2659 {
2660 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2661 bgp_clear_adj_in (peer, afi, safi);
2662 else
hassoe0701b72004-05-20 09:19:34 +00002663 {
2664 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2665 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2666 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2667 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2668 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2669 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2670 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2671 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2672
2673 peer_change_action (peer, afi, safi, action.type);
2674 }
paul718e3742002-12-13 20:15:29 +00002675 }
2676 }
2677 }
2678 return 0;
2679}
2680
2681int
2682peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2683{
2684 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2685}
2686
2687int
2688peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2689{
2690 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2691}
2692
2693/* EBGP multihop configuration. */
2694int
2695peer_ebgp_multihop_set (struct peer *peer, int ttl)
2696{
2697 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002698 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002699 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002700
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002701 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002702 return 0;
2703
Nick Hilliardfa411a22011-03-23 15:33:17 +00002704 /* see comment in peer_ttl_security_hops_set() */
2705 if (ttl != MAXTTL)
2706 {
2707 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2708 {
2709 group = peer->group;
2710 if (group->conf->gtsm_hops != 0)
2711 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2712
2713 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2714 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002715 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002716 continue;
2717
2718 if (peer1->gtsm_hops != 0)
2719 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2720 }
2721 }
2722 else
2723 {
2724 if (peer->gtsm_hops != 0)
2725 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2726 }
2727 }
2728
paul718e3742002-12-13 20:15:29 +00002729 peer->ttl = ttl;
2730
2731 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2732 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002733 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002734 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002735 }
2736 else
2737 {
2738 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002739 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002740 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002741 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002742 continue;
paul718e3742002-12-13 20:15:29 +00002743
pauleb821182004-05-01 08:44:08 +00002744 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002745
pauleb821182004-05-01 08:44:08 +00002746 if (peer->fd >= 0)
2747 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2748 }
paul718e3742002-12-13 20:15:29 +00002749 }
2750 return 0;
2751}
2752
2753int
2754peer_ebgp_multihop_unset (struct peer *peer)
2755{
2756 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002757 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002758
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002759 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002760 return 0;
2761
Nick Hilliardfa411a22011-03-23 15:33:17 +00002762 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2763 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2764
paul718e3742002-12-13 20:15:29 +00002765 if (peer_group_active (peer))
2766 peer->ttl = peer->group->conf->ttl;
2767 else
2768 peer->ttl = 1;
2769
2770 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2771 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002772 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002773 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002774 }
2775 else
2776 {
2777 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002778 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002779 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002780 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002781 continue;
paul718e3742002-12-13 20:15:29 +00002782
pauleb821182004-05-01 08:44:08 +00002783 peer->ttl = 1;
2784
2785 if (peer->fd >= 0)
2786 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2787 }
paul718e3742002-12-13 20:15:29 +00002788 }
2789 return 0;
2790}
2791
2792/* Neighbor description. */
2793int
2794peer_description_set (struct peer *peer, char *desc)
2795{
2796 if (peer->desc)
2797 XFREE (MTYPE_PEER_DESC, peer->desc);
2798
2799 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2800
2801 return 0;
2802}
2803
2804int
2805peer_description_unset (struct peer *peer)
2806{
2807 if (peer->desc)
2808 XFREE (MTYPE_PEER_DESC, peer->desc);
2809
2810 peer->desc = NULL;
2811
2812 return 0;
2813}
2814
2815/* Neighbor update-source. */
2816int
paulfd79ac92004-10-13 05:06:08 +00002817peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002818{
2819 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002820 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002821
2822 if (peer->update_if)
2823 {
2824 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2825 && strcmp (peer->update_if, ifname) == 0)
2826 return 0;
2827
2828 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2829 peer->update_if = NULL;
2830 }
2831
2832 if (peer->update_source)
2833 {
2834 sockunion_free (peer->update_source);
2835 peer->update_source = NULL;
2836 }
2837
2838 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2839
2840 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2841 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002842 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002843 {
2844 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2845 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2846 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2847 }
paul718e3742002-12-13 20:15:29 +00002848 else
2849 BGP_EVENT_ADD (peer, BGP_Stop);
2850 return 0;
2851 }
2852
2853 /* peer-group member updates. */
2854 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002855 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002856 {
2857 if (peer->update_if)
2858 {
2859 if (strcmp (peer->update_if, ifname) == 0)
2860 continue;
2861
2862 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2863 peer->update_if = NULL;
2864 }
2865
2866 if (peer->update_source)
2867 {
2868 sockunion_free (peer->update_source);
2869 peer->update_source = NULL;
2870 }
2871
2872 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2873
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002874 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002875 {
2876 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2877 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2878 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2879 }
paul718e3742002-12-13 20:15:29 +00002880 else
2881 BGP_EVENT_ADD (peer, BGP_Stop);
2882 }
2883 return 0;
2884}
2885
2886int
2887peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2888{
2889 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002890 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002891
2892 if (peer->update_source)
2893 {
2894 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2895 && sockunion_cmp (peer->update_source, su) == 0)
2896 return 0;
2897 sockunion_free (peer->update_source);
2898 peer->update_source = NULL;
2899 }
2900
2901 if (peer->update_if)
2902 {
2903 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2904 peer->update_if = NULL;
2905 }
2906
2907 peer->update_source = sockunion_dup (su);
2908
2909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2910 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002911 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002912 {
2913 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2914 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2915 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2916 }
paul718e3742002-12-13 20:15:29 +00002917 else
2918 BGP_EVENT_ADD (peer, BGP_Stop);
2919 return 0;
2920 }
2921
2922 /* peer-group member updates. */
2923 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002924 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002925 {
2926 if (peer->update_source)
2927 {
2928 if (sockunion_cmp (peer->update_source, su) == 0)
2929 continue;
2930 sockunion_free (peer->update_source);
2931 peer->update_source = NULL;
2932 }
2933
2934 if (peer->update_if)
2935 {
2936 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2937 peer->update_if = NULL;
2938 }
2939
2940 peer->update_source = sockunion_dup (su);
2941
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002942 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002943 {
2944 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2945 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2946 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2947 }
paul718e3742002-12-13 20:15:29 +00002948 else
2949 BGP_EVENT_ADD (peer, BGP_Stop);
2950 }
2951 return 0;
2952}
2953
2954int
2955peer_update_source_unset (struct peer *peer)
2956{
2957 union sockunion *su;
2958 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002959 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002960
2961 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2962 && ! peer->update_source
2963 && ! peer->update_if)
2964 return 0;
2965
2966 if (peer->update_source)
2967 {
2968 sockunion_free (peer->update_source);
2969 peer->update_source = NULL;
2970 }
2971 if (peer->update_if)
2972 {
2973 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2974 peer->update_if = NULL;
2975 }
2976
2977 if (peer_group_active (peer))
2978 {
2979 group = peer->group;
2980
2981 if (group->conf->update_source)
2982 {
2983 su = sockunion_dup (group->conf->update_source);
2984 peer->update_source = su;
2985 }
2986 else if (group->conf->update_if)
2987 peer->update_if =
2988 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2989 }
2990
2991 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2992 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002993 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002994 {
2995 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2996 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2997 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2998 }
paul718e3742002-12-13 20:15:29 +00002999 else
3000 BGP_EVENT_ADD (peer, BGP_Stop);
3001 return 0;
3002 }
3003
3004 /* peer-group member updates. */
3005 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003006 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003007 {
3008 if (! peer->update_source && ! peer->update_if)
3009 continue;
3010
3011 if (peer->update_source)
3012 {
3013 sockunion_free (peer->update_source);
3014 peer->update_source = NULL;
3015 }
3016
3017 if (peer->update_if)
3018 {
3019 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3020 peer->update_if = NULL;
3021 }
3022
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003023 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003024 {
3025 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3026 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3027 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3028 }
paul718e3742002-12-13 20:15:29 +00003029 else
3030 BGP_EVENT_ADD (peer, BGP_Stop);
3031 }
3032 return 0;
3033}
3034
3035int
3036peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003037 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003038{
3039 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003040 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003041
3042 /* Adress family must be activated. */
3043 if (! peer->afc[afi][safi])
3044 return BGP_ERR_PEER_INACTIVE;
3045
3046 /* Default originate can't be used for peer group memeber. */
3047 if (peer_is_group_member (peer, afi, safi))
3048 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3049
3050 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3051 || (rmap && ! peer->default_rmap[afi][safi].name)
3052 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3053 {
3054 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3055
3056 if (rmap)
3057 {
3058 if (peer->default_rmap[afi][safi].name)
3059 free (peer->default_rmap[afi][safi].name);
3060 peer->default_rmap[afi][safi].name = strdup (rmap);
3061 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3062 }
3063 }
3064
3065 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3066 {
3067 if (peer->status == Established && peer->afc_nego[afi][safi])
3068 bgp_default_originate (peer, afi, safi, 0);
3069 return 0;
3070 }
3071
3072 /* peer-group member updates. */
3073 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003074 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003075 {
3076 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3077
3078 if (rmap)
3079 {
3080 if (peer->default_rmap[afi][safi].name)
3081 free (peer->default_rmap[afi][safi].name);
3082 peer->default_rmap[afi][safi].name = strdup (rmap);
3083 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3084 }
3085
3086 if (peer->status == Established && peer->afc_nego[afi][safi])
3087 bgp_default_originate (peer, afi, safi, 0);
3088 }
3089 return 0;
3090}
3091
3092int
3093peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3094{
3095 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003096 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003097
3098 /* Adress family must be activated. */
3099 if (! peer->afc[afi][safi])
3100 return BGP_ERR_PEER_INACTIVE;
3101
3102 /* Default originate can't be used for peer group memeber. */
3103 if (peer_is_group_member (peer, afi, safi))
3104 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3105
3106 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3107 {
3108 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3109
3110 if (peer->default_rmap[afi][safi].name)
3111 free (peer->default_rmap[afi][safi].name);
3112 peer->default_rmap[afi][safi].name = NULL;
3113 peer->default_rmap[afi][safi].map = NULL;
3114 }
3115
3116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3117 {
3118 if (peer->status == Established && peer->afc_nego[afi][safi])
3119 bgp_default_originate (peer, afi, safi, 1);
3120 return 0;
3121 }
3122
3123 /* peer-group member updates. */
3124 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003125 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003126 {
3127 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3128
3129 if (peer->default_rmap[afi][safi].name)
3130 free (peer->default_rmap[afi][safi].name);
3131 peer->default_rmap[afi][safi].name = NULL;
3132 peer->default_rmap[afi][safi].map = NULL;
3133
3134 if (peer->status == Established && peer->afc_nego[afi][safi])
3135 bgp_default_originate (peer, afi, safi, 1);
3136 }
3137 return 0;
3138}
3139
3140int
3141peer_port_set (struct peer *peer, u_int16_t port)
3142{
3143 peer->port = port;
3144 return 0;
3145}
3146
3147int
3148peer_port_unset (struct peer *peer)
3149{
3150 peer->port = BGP_PORT_DEFAULT;
3151 return 0;
3152}
3153
3154/* neighbor weight. */
3155int
3156peer_weight_set (struct peer *peer, u_int16_t weight)
3157{
3158 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003159 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003160
3161 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3162 peer->weight = 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 = group->conf->weight;
3172 }
3173 return 0;
3174}
3175
3176int
3177peer_weight_unset (struct peer *peer)
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 /* Set default weight. */
3183 if (peer_group_active (peer))
3184 peer->weight = peer->group->conf->weight;
3185 else
3186 peer->weight = 0;
3187
3188 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3189
3190 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3191 return 0;
3192
3193 /* peer-group member updates. */
3194 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003195 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003196 {
3197 peer->weight = 0;
3198 }
3199 return 0;
3200}
3201
3202int
3203peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3204{
3205 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003206 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003207
3208 /* Not for peer group memeber. */
3209 if (peer_group_active (peer))
3210 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3211
3212 /* keepalive value check. */
3213 if (keepalive > 65535)
3214 return BGP_ERR_INVALID_VALUE;
3215
3216 /* Holdtime value check. */
3217 if (holdtime > 65535)
3218 return BGP_ERR_INVALID_VALUE;
3219
3220 /* Holdtime value must be either 0 or greater than 3. */
3221 if (holdtime < 3 && holdtime != 0)
3222 return BGP_ERR_INVALID_VALUE;
3223
3224 /* Set value to the configuration. */
3225 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3226 peer->holdtime = holdtime;
3227 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3228
3229 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3230 return 0;
3231
3232 /* peer-group member updates. */
3233 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003234 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003235 {
3236 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3237 peer->holdtime = group->conf->holdtime;
3238 peer->keepalive = group->conf->keepalive;
3239 }
3240 return 0;
3241}
3242
3243int
3244peer_timers_unset (struct peer *peer)
3245{
3246 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003247 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003248
3249 if (peer_group_active (peer))
3250 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3251
3252 /* Clear configuration. */
3253 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3254 peer->keepalive = 0;
3255 peer->holdtime = 0;
3256
3257 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3258 return 0;
3259
3260 /* peer-group member updates. */
3261 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003262 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003263 {
3264 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3265 peer->holdtime = 0;
3266 peer->keepalive = 0;
3267 }
3268
3269 return 0;
3270}
3271
3272int
3273peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3274{
3275 if (peer_group_active (peer))
3276 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3277
3278 if (connect > 65535)
3279 return BGP_ERR_INVALID_VALUE;
3280
3281 /* Set value to the configuration. */
3282 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3283 peer->connect = connect;
3284
3285 /* Set value to timer setting. */
3286 peer->v_connect = connect;
3287
3288 return 0;
3289}
3290
3291int
3292peer_timers_connect_unset (struct peer *peer)
3293{
3294 if (peer_group_active (peer))
3295 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3296
3297 /* Clear configuration. */
3298 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3299 peer->connect = 0;
3300
3301 /* Set timer setting to default value. */
3302 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3303
3304 return 0;
3305}
3306
3307int
3308peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3309{
3310 if (peer_group_active (peer))
3311 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3312
3313 if (routeadv > 600)
3314 return BGP_ERR_INVALID_VALUE;
3315
3316 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3317 peer->routeadv = routeadv;
3318 peer->v_routeadv = routeadv;
3319
3320 return 0;
3321}
3322
3323int
3324peer_advertise_interval_unset (struct peer *peer)
3325{
3326 if (peer_group_active (peer))
3327 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3328
3329 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3330 peer->routeadv = 0;
3331
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003332 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003333 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3334 else
3335 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3336
3337 return 0;
3338}
3339
paul718e3742002-12-13 20:15:29 +00003340/* neighbor interface */
3341int
paulfd79ac92004-10-13 05:06:08 +00003342peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003343{
3344 if (peer->ifname)
3345 free (peer->ifname);
3346 peer->ifname = strdup (str);
3347
3348 return 0;
3349}
3350
3351int
3352peer_interface_unset (struct peer *peer)
3353{
3354 if (peer->ifname)
3355 free (peer->ifname);
3356 peer->ifname = NULL;
3357
3358 return 0;
3359}
3360
3361/* Allow-as in. */
3362int
3363peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3364{
3365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003367
3368 if (allow_num < 1 || allow_num > 10)
3369 return BGP_ERR_INVALID_VALUE;
3370
3371 if (peer->allowas_in[afi][safi] != allow_num)
3372 {
3373 peer->allowas_in[afi][safi] = allow_num;
3374 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3375 peer_change_action (peer, afi, safi, peer_change_reset_in);
3376 }
3377
3378 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3379 return 0;
3380
3381 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003382 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003383 {
3384 if (peer->allowas_in[afi][safi] != allow_num)
3385 {
3386 peer->allowas_in[afi][safi] = allow_num;
3387 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3388 peer_change_action (peer, afi, safi, peer_change_reset_in);
3389 }
3390
3391 }
3392 return 0;
3393}
3394
3395int
3396peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3397{
3398 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003399 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003400
3401 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3402 {
3403 peer->allowas_in[afi][safi] = 0;
3404 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3405 }
3406
3407 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3408 return 0;
3409
3410 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003411 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003412 {
3413 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3414 {
3415 peer->allowas_in[afi][safi] = 0;
3416 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3417 }
3418 }
3419 return 0;
3420}
3421
3422int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003423peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003424{
3425 struct bgp *bgp = peer->bgp;
3426 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003427 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003428
3429 if (peer_sort (peer) != BGP_PEER_EBGP
3430 && peer_sort (peer) != BGP_PEER_INTERNAL)
3431 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3432
3433 if (bgp->as == as)
3434 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3435
3436 if (peer_group_active (peer))
3437 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3438
Andrew Certain9d3f9702012-11-07 23:50:07 +00003439 if (peer->as == as)
3440 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3441
paul718e3742002-12-13 20:15:29 +00003442 if (peer->change_local_as == as &&
3443 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003444 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3445 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3446 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003447 return 0;
3448
3449 peer->change_local_as = as;
3450 if (no_prepend)
3451 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3452 else
3453 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3454
Andrew Certain9d3f9702012-11-07 23:50:07 +00003455 if (replace_as)
3456 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3457 else
3458 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3459
paul718e3742002-12-13 20:15:29 +00003460 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3461 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003462 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003463 {
3464 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3465 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3466 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3467 }
paul718e3742002-12-13 20:15:29 +00003468 else
3469 BGP_EVENT_ADD (peer, BGP_Stop);
3470
3471 return 0;
3472 }
3473
3474 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003475 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003476 {
3477 peer->change_local_as = as;
3478 if (no_prepend)
3479 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3480 else
3481 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3482
Andrew Certain9d3f9702012-11-07 23:50:07 +00003483 if (replace_as)
3484 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3485 else
3486 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3487
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003488 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003489 {
3490 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3491 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3492 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3493 }
paul718e3742002-12-13 20:15:29 +00003494 else
3495 BGP_EVENT_ADD (peer, BGP_Stop);
3496 }
3497
3498 return 0;
3499}
3500
3501int
3502peer_local_as_unset (struct peer *peer)
3503{
3504 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003505 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003506
3507 if (peer_group_active (peer))
3508 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3509
3510 if (! peer->change_local_as)
3511 return 0;
3512
3513 peer->change_local_as = 0;
3514 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003515 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003516
3517 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3518 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003519 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003520 {
3521 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3522 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3523 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3524 }
paul718e3742002-12-13 20:15:29 +00003525 else
3526 BGP_EVENT_ADD (peer, BGP_Stop);
3527
3528 return 0;
3529 }
3530
3531 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003532 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003533 {
3534 peer->change_local_as = 0;
3535 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003536 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003537
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003538 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003539 {
3540 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3541 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3542 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3543 }
paul718e3742002-12-13 20:15:29 +00003544 else
3545 BGP_EVENT_ADD (peer, BGP_Stop);
3546 }
3547 return 0;
3548}
3549
Paul Jakma0df7c912008-07-21 21:02:49 +00003550/* Set password for authenticating with the peer. */
3551int
3552peer_password_set (struct peer *peer, const char *password)
3553{
3554 struct listnode *nn, *nnode;
3555 int len = password ? strlen(password) : 0;
3556 int ret = BGP_SUCCESS;
3557
3558 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3559 return BGP_ERR_INVALID_VALUE;
3560
3561 if (peer->password && strcmp (peer->password, password) == 0
3562 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3563 return 0;
3564
3565 if (peer->password)
3566 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3567
3568 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3569
3570 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3571 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003572 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3573 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003574 else
3575 BGP_EVENT_ADD (peer, BGP_Stop);
3576
3577 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3578 }
3579
3580 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3581 {
3582 if (peer->password && strcmp (peer->password, password) == 0)
3583 continue;
3584
3585 if (peer->password)
3586 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3587
3588 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3589
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003590 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003591 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3592 else
3593 BGP_EVENT_ADD (peer, BGP_Stop);
3594
3595 if (bgp_md5_set (peer) < 0)
3596 ret = BGP_ERR_TCPSIG_FAILED;
3597 }
3598
3599 return ret;
3600}
3601
3602int
3603peer_password_unset (struct peer *peer)
3604{
3605 struct listnode *nn, *nnode;
3606
3607 if (!peer->password
3608 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3609 return 0;
3610
3611 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3612 {
3613 if (peer_group_active (peer)
3614 && peer->group->conf->password
3615 && strcmp (peer->group->conf->password, peer->password) == 0)
3616 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3617
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003618 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003619 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3620 else
3621 BGP_EVENT_ADD (peer, BGP_Stop);
3622
3623 if (peer->password)
3624 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3625
3626 peer->password = NULL;
3627
3628 bgp_md5_set (peer);
3629
3630 return 0;
3631 }
3632
3633 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3634 peer->password = NULL;
3635
3636 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3637 {
3638 if (!peer->password)
3639 continue;
3640
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003641 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003642 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3643 else
3644 BGP_EVENT_ADD (peer, BGP_Stop);
3645
3646 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3647 peer->password = NULL;
3648
3649 bgp_md5_set (peer);
3650 }
3651
3652 return 0;
3653}
3654
paul718e3742002-12-13 20:15:29 +00003655/* Set distribute list to the peer. */
3656int
3657peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003658 const char *name)
paul718e3742002-12-13 20:15:29 +00003659{
3660 struct bgp_filter *filter;
3661 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003662 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003663
3664 if (! peer->afc[afi][safi])
3665 return BGP_ERR_PEER_INACTIVE;
3666
3667 if (direct != FILTER_IN && direct != FILTER_OUT)
3668 return BGP_ERR_INVALID_VALUE;
3669
3670 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3671 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3672
3673 filter = &peer->filter[afi][safi];
3674
3675 if (filter->plist[direct].name)
3676 return BGP_ERR_PEER_FILTER_CONFLICT;
3677
3678 if (filter->dlist[direct].name)
3679 free (filter->dlist[direct].name);
3680 filter->dlist[direct].name = strdup (name);
3681 filter->dlist[direct].alist = access_list_lookup (afi, name);
3682
3683 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3684 return 0;
3685
3686 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003687 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003688 {
3689 filter = &peer->filter[afi][safi];
3690
3691 if (! peer->af_group[afi][safi])
3692 continue;
3693
3694 if (filter->dlist[direct].name)
3695 free (filter->dlist[direct].name);
3696 filter->dlist[direct].name = strdup (name);
3697 filter->dlist[direct].alist = access_list_lookup (afi, name);
3698 }
3699
3700 return 0;
3701}
3702
3703int
3704peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3705{
3706 struct bgp_filter *filter;
3707 struct bgp_filter *gfilter;
3708 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003709 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003710
3711 if (! peer->afc[afi][safi])
3712 return BGP_ERR_PEER_INACTIVE;
3713
3714 if (direct != FILTER_IN && direct != FILTER_OUT)
3715 return BGP_ERR_INVALID_VALUE;
3716
3717 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3718 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3719
3720 filter = &peer->filter[afi][safi];
3721
3722 /* apply peer-group filter */
3723 if (peer->af_group[afi][safi])
3724 {
3725 gfilter = &peer->group->conf->filter[afi][safi];
3726
3727 if (gfilter->dlist[direct].name)
3728 {
3729 if (filter->dlist[direct].name)
3730 free (filter->dlist[direct].name);
3731 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3732 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3733 return 0;
3734 }
3735 }
3736
3737 if (filter->dlist[direct].name)
3738 free (filter->dlist[direct].name);
3739 filter->dlist[direct].name = NULL;
3740 filter->dlist[direct].alist = NULL;
3741
3742 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3743 return 0;
3744
3745 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003747 {
3748 filter = &peer->filter[afi][safi];
3749
3750 if (! peer->af_group[afi][safi])
3751 continue;
3752
3753 if (filter->dlist[direct].name)
3754 free (filter->dlist[direct].name);
3755 filter->dlist[direct].name = NULL;
3756 filter->dlist[direct].alist = NULL;
3757 }
3758
3759 return 0;
3760}
3761
3762/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003763static void
paul718e3742002-12-13 20:15:29 +00003764peer_distribute_update (struct access_list *access)
3765{
3766 afi_t afi;
3767 safi_t safi;
3768 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003769 struct listnode *mnode, *mnnode;
3770 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003771 struct bgp *bgp;
3772 struct peer *peer;
3773 struct peer_group *group;
3774 struct bgp_filter *filter;
3775
paul1eb8ef22005-04-07 07:30:20 +00003776 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003777 {
paul1eb8ef22005-04-07 07:30:20 +00003778 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003779 {
3780 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3781 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3782 {
3783 filter = &peer->filter[afi][safi];
3784
3785 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3786 {
3787 if (filter->dlist[direct].name)
3788 filter->dlist[direct].alist =
3789 access_list_lookup (afi, filter->dlist[direct].name);
3790 else
3791 filter->dlist[direct].alist = NULL;
3792 }
3793 }
3794 }
paul1eb8ef22005-04-07 07:30:20 +00003795 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003796 {
3797 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3798 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3799 {
3800 filter = &group->conf->filter[afi][safi];
3801
3802 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3803 {
3804 if (filter->dlist[direct].name)
3805 filter->dlist[direct].alist =
3806 access_list_lookup (afi, filter->dlist[direct].name);
3807 else
3808 filter->dlist[direct].alist = NULL;
3809 }
3810 }
3811 }
3812 }
3813}
3814
3815/* Set prefix list to the peer. */
3816int
3817peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003818 const char *name)
paul718e3742002-12-13 20:15:29 +00003819{
3820 struct bgp_filter *filter;
3821 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003822 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003823
3824 if (! peer->afc[afi][safi])
3825 return BGP_ERR_PEER_INACTIVE;
3826
3827 if (direct != FILTER_IN && direct != FILTER_OUT)
3828 return BGP_ERR_INVALID_VALUE;
3829
3830 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3831 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3832
3833 filter = &peer->filter[afi][safi];
3834
3835 if (filter->dlist[direct].name)
3836 return BGP_ERR_PEER_FILTER_CONFLICT;
3837
3838 if (filter->plist[direct].name)
3839 free (filter->plist[direct].name);
3840 filter->plist[direct].name = strdup (name);
3841 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3842
3843 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3844 return 0;
3845
3846 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003847 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003848 {
3849 filter = &peer->filter[afi][safi];
3850
3851 if (! peer->af_group[afi][safi])
3852 continue;
3853
3854 if (filter->plist[direct].name)
3855 free (filter->plist[direct].name);
3856 filter->plist[direct].name = strdup (name);
3857 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3858 }
3859 return 0;
3860}
3861
3862int
3863peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3864{
3865 struct bgp_filter *filter;
3866 struct bgp_filter *gfilter;
3867 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003868 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003869
3870 if (! peer->afc[afi][safi])
3871 return BGP_ERR_PEER_INACTIVE;
3872
3873 if (direct != FILTER_IN && direct != FILTER_OUT)
3874 return BGP_ERR_INVALID_VALUE;
3875
3876 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3877 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3878
3879 filter = &peer->filter[afi][safi];
3880
3881 /* apply peer-group filter */
3882 if (peer->af_group[afi][safi])
3883 {
3884 gfilter = &peer->group->conf->filter[afi][safi];
3885
3886 if (gfilter->plist[direct].name)
3887 {
3888 if (filter->plist[direct].name)
3889 free (filter->plist[direct].name);
3890 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3891 filter->plist[direct].plist = gfilter->plist[direct].plist;
3892 return 0;
3893 }
3894 }
3895
3896 if (filter->plist[direct].name)
3897 free (filter->plist[direct].name);
3898 filter->plist[direct].name = NULL;
3899 filter->plist[direct].plist = NULL;
3900
3901 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3902 return 0;
3903
3904 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003905 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003906 {
3907 filter = &peer->filter[afi][safi];
3908
3909 if (! peer->af_group[afi][safi])
3910 continue;
3911
3912 if (filter->plist[direct].name)
3913 free (filter->plist[direct].name);
3914 filter->plist[direct].name = NULL;
3915 filter->plist[direct].plist = NULL;
3916 }
3917
3918 return 0;
3919}
3920
3921/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003922static void
paul718e3742002-12-13 20:15:29 +00003923peer_prefix_list_update (struct prefix_list *plist)
3924{
paul1eb8ef22005-04-07 07:30:20 +00003925 struct listnode *mnode, *mnnode;
3926 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003927 struct bgp *bgp;
3928 struct peer *peer;
3929 struct peer_group *group;
3930 struct bgp_filter *filter;
3931 afi_t afi;
3932 safi_t safi;
3933 int direct;
3934
paul1eb8ef22005-04-07 07:30:20 +00003935 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003936 {
paul1eb8ef22005-04-07 07:30:20 +00003937 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003938 {
3939 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3940 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3941 {
3942 filter = &peer->filter[afi][safi];
3943
3944 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3945 {
3946 if (filter->plist[direct].name)
3947 filter->plist[direct].plist =
3948 prefix_list_lookup (afi, filter->plist[direct].name);
3949 else
3950 filter->plist[direct].plist = NULL;
3951 }
3952 }
3953 }
paul1eb8ef22005-04-07 07:30:20 +00003954 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003955 {
3956 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3957 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3958 {
3959 filter = &group->conf->filter[afi][safi];
3960
3961 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3962 {
3963 if (filter->plist[direct].name)
3964 filter->plist[direct].plist =
3965 prefix_list_lookup (afi, filter->plist[direct].name);
3966 else
3967 filter->plist[direct].plist = NULL;
3968 }
3969 }
3970 }
3971 }
3972}
3973
3974int
3975peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003976 const char *name)
paul718e3742002-12-13 20:15:29 +00003977{
3978 struct bgp_filter *filter;
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
3985 if (direct != FILTER_IN && direct != FILTER_OUT)
3986 return BGP_ERR_INVALID_VALUE;
3987
3988 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3989 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3990
3991 filter = &peer->filter[afi][safi];
3992
3993 if (filter->aslist[direct].name)
3994 free (filter->aslist[direct].name);
3995 filter->aslist[direct].name = strdup (name);
3996 filter->aslist[direct].aslist = as_list_lookup (name);
3997
3998 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3999 return 0;
4000
4001 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004002 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004003 {
4004 filter = &peer->filter[afi][safi];
4005
4006 if (! peer->af_group[afi][safi])
4007 continue;
4008
4009 if (filter->aslist[direct].name)
4010 free (filter->aslist[direct].name);
4011 filter->aslist[direct].name = strdup (name);
4012 filter->aslist[direct].aslist = as_list_lookup (name);
4013 }
4014 return 0;
4015}
4016
4017int
4018peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4019{
4020 struct bgp_filter *filter;
4021 struct bgp_filter *gfilter;
4022 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004023 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004024
4025 if (! peer->afc[afi][safi])
4026 return BGP_ERR_PEER_INACTIVE;
4027
hassob5f29602005-05-25 21:00:28 +00004028 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004029 return BGP_ERR_INVALID_VALUE;
4030
hassob5f29602005-05-25 21:00:28 +00004031 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004032 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4033
4034 filter = &peer->filter[afi][safi];
4035
4036 /* apply peer-group filter */
4037 if (peer->af_group[afi][safi])
4038 {
4039 gfilter = &peer->group->conf->filter[afi][safi];
4040
4041 if (gfilter->aslist[direct].name)
4042 {
4043 if (filter->aslist[direct].name)
4044 free (filter->aslist[direct].name);
4045 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4046 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4047 return 0;
4048 }
4049 }
4050
4051 if (filter->aslist[direct].name)
4052 free (filter->aslist[direct].name);
4053 filter->aslist[direct].name = NULL;
4054 filter->aslist[direct].aslist = NULL;
4055
4056 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4057 return 0;
4058
4059 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004060 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004061 {
4062 filter = &peer->filter[afi][safi];
4063
4064 if (! peer->af_group[afi][safi])
4065 continue;
4066
4067 if (filter->aslist[direct].name)
4068 free (filter->aslist[direct].name);
4069 filter->aslist[direct].name = NULL;
4070 filter->aslist[direct].aslist = NULL;
4071 }
4072
4073 return 0;
4074}
4075
paul94f2b392005-06-28 12:44:16 +00004076static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004077peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004078{
4079 afi_t afi;
4080 safi_t safi;
4081 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004082 struct listnode *mnode, *mnnode;
4083 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004084 struct bgp *bgp;
4085 struct peer *peer;
4086 struct peer_group *group;
4087 struct bgp_filter *filter;
4088
paul1eb8ef22005-04-07 07:30:20 +00004089 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004090 {
paul1eb8ef22005-04-07 07:30:20 +00004091 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004092 {
4093 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4094 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4095 {
4096 filter = &peer->filter[afi][safi];
4097
4098 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4099 {
4100 if (filter->aslist[direct].name)
4101 filter->aslist[direct].aslist =
4102 as_list_lookup (filter->aslist[direct].name);
4103 else
4104 filter->aslist[direct].aslist = NULL;
4105 }
4106 }
4107 }
paul1eb8ef22005-04-07 07:30:20 +00004108 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004109 {
4110 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4111 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4112 {
4113 filter = &group->conf->filter[afi][safi];
4114
4115 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4116 {
4117 if (filter->aslist[direct].name)
4118 filter->aslist[direct].aslist =
4119 as_list_lookup (filter->aslist[direct].name);
4120 else
4121 filter->aslist[direct].aslist = NULL;
4122 }
4123 }
4124 }
4125 }
4126}
4127
4128/* Set route-map to the peer. */
4129int
4130peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004131 const char *name)
paul718e3742002-12-13 20:15:29 +00004132{
4133 struct bgp_filter *filter;
4134 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004135 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004136
4137 if (! peer->afc[afi][safi])
4138 return BGP_ERR_PEER_INACTIVE;
4139
paulfee0f4c2004-09-13 05:12:46 +00004140 if (direct != RMAP_IN && direct != RMAP_OUT &&
4141 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004142 return BGP_ERR_INVALID_VALUE;
4143
paulfee0f4c2004-09-13 05:12:46 +00004144 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4145 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004146 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4147
4148 filter = &peer->filter[afi][safi];
4149
4150 if (filter->map[direct].name)
4151 free (filter->map[direct].name);
4152
4153 filter->map[direct].name = strdup (name);
4154 filter->map[direct].map = route_map_lookup_by_name (name);
4155
4156 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4157 return 0;
4158
4159 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004160 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004161 {
4162 filter = &peer->filter[afi][safi];
4163
4164 if (! peer->af_group[afi][safi])
4165 continue;
4166
4167 if (filter->map[direct].name)
4168 free (filter->map[direct].name);
4169 filter->map[direct].name = strdup (name);
4170 filter->map[direct].map = route_map_lookup_by_name (name);
4171 }
4172 return 0;
4173}
4174
4175/* Unset route-map from the peer. */
4176int
4177peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4178{
4179 struct bgp_filter *filter;
4180 struct bgp_filter *gfilter;
4181 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004182 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004183
4184 if (! peer->afc[afi][safi])
4185 return BGP_ERR_PEER_INACTIVE;
4186
hassob5f29602005-05-25 21:00:28 +00004187 if (direct != RMAP_IN && direct != RMAP_OUT &&
4188 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004189 return BGP_ERR_INVALID_VALUE;
4190
hassob5f29602005-05-25 21:00:28 +00004191 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4192 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004193 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4194
4195 filter = &peer->filter[afi][safi];
4196
4197 /* apply peer-group filter */
4198 if (peer->af_group[afi][safi])
4199 {
4200 gfilter = &peer->group->conf->filter[afi][safi];
4201
4202 if (gfilter->map[direct].name)
4203 {
4204 if (filter->map[direct].name)
4205 free (filter->map[direct].name);
4206 filter->map[direct].name = strdup (gfilter->map[direct].name);
4207 filter->map[direct].map = gfilter->map[direct].map;
4208 return 0;
4209 }
4210 }
4211
4212 if (filter->map[direct].name)
4213 free (filter->map[direct].name);
4214 filter->map[direct].name = NULL;
4215 filter->map[direct].map = NULL;
4216
4217 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4218 return 0;
4219
4220 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004221 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004222 {
4223 filter = &peer->filter[afi][safi];
4224
4225 if (! peer->af_group[afi][safi])
4226 continue;
4227
4228 if (filter->map[direct].name)
4229 free (filter->map[direct].name);
4230 filter->map[direct].name = NULL;
4231 filter->map[direct].map = NULL;
4232 }
4233 return 0;
4234}
4235
4236/* Set unsuppress-map to the peer. */
4237int
paulfd79ac92004-10-13 05:06:08 +00004238peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4239 const char *name)
paul718e3742002-12-13 20:15:29 +00004240{
4241 struct bgp_filter *filter;
4242 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004243 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004244
4245 if (! peer->afc[afi][safi])
4246 return BGP_ERR_PEER_INACTIVE;
4247
4248 if (peer_is_group_member (peer, afi, safi))
4249 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4250
4251 filter = &peer->filter[afi][safi];
4252
4253 if (filter->usmap.name)
4254 free (filter->usmap.name);
4255
4256 filter->usmap.name = strdup (name);
4257 filter->usmap.map = route_map_lookup_by_name (name);
4258
4259 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4260 return 0;
4261
4262 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004263 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004264 {
4265 filter = &peer->filter[afi][safi];
4266
4267 if (! peer->af_group[afi][safi])
4268 continue;
4269
4270 if (filter->usmap.name)
4271 free (filter->usmap.name);
4272 filter->usmap.name = strdup (name);
4273 filter->usmap.map = route_map_lookup_by_name (name);
4274 }
4275 return 0;
4276}
4277
4278/* Unset route-map from the peer. */
4279int
4280peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4281{
4282 struct bgp_filter *filter;
4283 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004284 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004285
4286 if (! peer->afc[afi][safi])
4287 return BGP_ERR_PEER_INACTIVE;
4288
4289 if (peer_is_group_member (peer, afi, safi))
4290 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4291
4292 filter = &peer->filter[afi][safi];
4293
4294 if (filter->usmap.name)
4295 free (filter->usmap.name);
4296 filter->usmap.name = NULL;
4297 filter->usmap.map = NULL;
4298
4299 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4300 return 0;
4301
4302 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004303 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004304 {
4305 filter = &peer->filter[afi][safi];
4306
4307 if (! peer->af_group[afi][safi])
4308 continue;
4309
4310 if (filter->usmap.name)
4311 free (filter->usmap.name);
4312 filter->usmap.name = NULL;
4313 filter->usmap.map = NULL;
4314 }
4315 return 0;
4316}
4317
4318int
4319peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004320 u_int32_t max, u_char threshold,
4321 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004322{
4323 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004324 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004325
4326 if (! peer->afc[afi][safi])
4327 return BGP_ERR_PEER_INACTIVE;
4328
4329 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4330 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004331 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004332 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004333 if (warning)
4334 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4335 else
4336 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4337
4338 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4339 return 0;
4340
4341 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004342 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004343 {
4344 if (! peer->af_group[afi][safi])
4345 continue;
4346
4347 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4348 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004349 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004350 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004351 if (warning)
4352 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4353 else
4354 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4355 }
4356 return 0;
4357}
4358
4359int
4360peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4361{
4362 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004363 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004364
4365 if (! peer->afc[afi][safi])
4366 return BGP_ERR_PEER_INACTIVE;
4367
4368 /* apply peer-group config */
4369 if (peer->af_group[afi][safi])
4370 {
4371 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4372 PEER_FLAG_MAX_PREFIX))
4373 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4374 else
4375 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4376
4377 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4378 PEER_FLAG_MAX_PREFIX_WARNING))
4379 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4380 else
4381 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4382
4383 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004384 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004385 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004386 return 0;
4387 }
4388
4389 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4390 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4391 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004392 peer->pmax_threshold[afi][safi] = 0;
4393 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004394
4395 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4396 return 0;
4397
4398 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004399 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004400 {
4401 if (! peer->af_group[afi][safi])
4402 continue;
4403
4404 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4405 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4406 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004407 peer->pmax_threshold[afi][safi] = 0;
4408 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004409 }
4410 return 0;
4411}
David Lamparter5f9adb52014-05-19 23:15:02 +02004412
4413static int is_ebgp_multihop_configured (struct peer *peer)
4414{
4415 struct peer_group *group;
4416 struct listnode *node, *nnode;
4417 struct peer *peer1;
4418
4419 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4420 {
4421 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004422 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4423 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004424 return 1;
4425
4426 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4427 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004428 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4429 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004430 return 1;
4431 }
4432 }
4433 else
4434 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004435 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4436 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004437 return 1;
4438 }
4439 return 0;
4440}
4441
Nick Hilliardfa411a22011-03-23 15:33:17 +00004442/* Set # of hops between us and BGP peer. */
4443int
4444peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4445{
4446 struct peer_group *group;
4447 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004448 int ret;
4449
4450 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4451
Nick Hilliardfa411a22011-03-23 15:33:17 +00004452 /* We cannot configure ttl-security hops when ebgp-multihop is already
4453 set. For non peer-groups, the check is simple. For peer-groups, it's
4454 slightly messy, because we need to check both the peer-group structure
4455 and all peer-group members for any trace of ebgp-multihop configuration
4456 before actually applying the ttl-security rules. Cisco really made a
4457 mess of this configuration parameter, and OpenBGPD got it right.
4458 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004459
David Lamparter5f9adb52014-05-19 23:15:02 +02004460 if (peer->gtsm_hops == 0)
4461 {
4462 if (is_ebgp_multihop_configured (peer))
4463 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004464
David Lamparter5f9adb52014-05-19 23:15:02 +02004465 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004466 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004467 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4468 if (ret != 0)
4469 return ret;
4470 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004471
Nick Hilliardfa411a22011-03-23 15:33:17 +00004472 peer->gtsm_hops = gtsm_hops;
4473
Nick Hilliardfa411a22011-03-23 15:33:17 +00004474 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4475 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004476 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004477 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4478 }
4479 else
4480 {
4481 group = peer->group;
4482 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4483 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004484 peer->gtsm_hops = group->conf->gtsm_hops;
4485
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004486 /* Change setting of existing peer
4487 * established then change value (may break connectivity)
4488 * not established yet (teardown session and restart)
4489 * no session then do nothing (will get handled by next connection)
4490 */
4491 if (peer->status == Established)
4492 {
4493 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4494 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4495 MAXTTL + 1 - peer->gtsm_hops);
4496 }
4497 else if (peer->status < Established)
4498 {
4499 if (BGP_DEBUG (events, EVENTS))
4500 zlog_debug ("%s Min-ttl changed", peer->host);
4501 BGP_EVENT_ADD (peer, BGP_Stop);
4502 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004503 }
4504 }
4505
4506 return 0;
4507}
4508
4509int
4510peer_ttl_security_hops_unset (struct peer *peer)
4511{
4512 struct peer_group *group;
4513 struct listnode *node, *nnode;
4514 struct peer *opeer;
4515
4516 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4517
Nick Hilliardfa411a22011-03-23 15:33:17 +00004518 /* if a peer-group member, then reset to peer-group default rather than 0 */
4519 if (peer_group_active (peer))
4520 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4521 else
4522 peer->gtsm_hops = 0;
4523
4524 opeer = peer;
4525 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4526 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004527 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004528 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4529 }
4530 else
4531 {
4532 group = peer->group;
4533 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4534 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004535 peer->gtsm_hops = 0;
4536
4537 if (peer->fd >= 0)
4538 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4539 }
4540 }
4541
4542 return peer_ebgp_multihop_unset (opeer);
4543}
4544
paul718e3742002-12-13 20:15:29 +00004545int
4546peer_clear (struct peer *peer)
4547{
4548 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4549 {
hasso0a486e52005-02-01 20:57:17 +00004550 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4551 {
4552 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4553 if (peer->t_pmax_restart)
4554 {
4555 BGP_TIMER_OFF (peer->t_pmax_restart);
4556 if (BGP_DEBUG (events, EVENTS))
4557 zlog_debug ("%s Maximum-prefix restart timer canceled",
4558 peer->host);
4559 }
4560 BGP_EVENT_ADD (peer, BGP_Start);
4561 return 0;
4562 }
4563
paul718e3742002-12-13 20:15:29 +00004564 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004565 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004566 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4567 BGP_NOTIFY_CEASE_ADMIN_RESET);
4568 else
4569 BGP_EVENT_ADD (peer, BGP_Stop);
4570 }
4571 return 0;
4572}
4573
4574int
4575peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4576 enum bgp_clear_type stype)
4577{
4578 if (peer->status != Established)
4579 return 0;
4580
4581 if (! peer->afc[afi][safi])
4582 return BGP_ERR_AF_UNCONFIGURED;
4583
paulfee0f4c2004-09-13 05:12:46 +00004584 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4585 {
4586 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4587 return 0;
4588 bgp_check_local_routes_rsclient (peer, afi, safi);
4589 bgp_soft_reconfig_rsclient (peer, afi, safi);
4590 }
4591
paul718e3742002-12-13 20:15:29 +00004592 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4593 bgp_announce_route (peer, afi, safi);
4594
4595 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4596 {
4597 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4598 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4599 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4600 {
4601 struct bgp_filter *filter = &peer->filter[afi][safi];
4602 u_char prefix_type;
4603
4604 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4605 prefix_type = ORF_TYPE_PREFIX;
4606 else
4607 prefix_type = ORF_TYPE_PREFIX_OLD;
4608
4609 if (filter->plist[FILTER_IN].plist)
4610 {
4611 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4612 bgp_route_refresh_send (peer, afi, safi,
4613 prefix_type, REFRESH_DEFER, 1);
4614 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4615 REFRESH_IMMEDIATE, 0);
4616 }
4617 else
4618 {
4619 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4620 bgp_route_refresh_send (peer, afi, safi,
4621 prefix_type, REFRESH_IMMEDIATE, 1);
4622 else
4623 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4624 }
4625 return 0;
4626 }
4627 }
4628
4629 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4630 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4631 {
4632 /* If neighbor has soft reconfiguration inbound flag.
4633 Use Adj-RIB-In database. */
4634 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4635 bgp_soft_reconfig_in (peer, afi, safi);
4636 else
4637 {
4638 /* If neighbor has route refresh capability, send route refresh
4639 message to the peer. */
4640 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4641 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4642 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4643 else
4644 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4645 }
4646 }
4647 return 0;
4648}
4649
paulfd79ac92004-10-13 05:06:08 +00004650/* Display peer uptime.*/
4651/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004652char *
4653peer_uptime (time_t uptime2, char *buf, size_t len)
4654{
4655 time_t uptime1;
4656 struct tm *tm;
4657
4658 /* Check buffer length. */
4659 if (len < BGP_UPTIME_LEN)
4660 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004661 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004662 /* XXX: should return status instead of buf... */
4663 snprintf (buf, len, "<error> ");
4664 return buf;
paul718e3742002-12-13 20:15:29 +00004665 }
4666
4667 /* If there is no connection has been done before print `never'. */
4668 if (uptime2 == 0)
4669 {
4670 snprintf (buf, len, "never ");
4671 return buf;
4672 }
4673
4674 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004675 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004676 uptime1 -= uptime2;
4677 tm = gmtime (&uptime1);
4678
4679 /* Making formatted timer strings. */
4680#define ONE_DAY_SECOND 60*60*24
4681#define ONE_WEEK_SECOND 60*60*24*7
4682
4683 if (uptime1 < ONE_DAY_SECOND)
4684 snprintf (buf, len, "%02d:%02d:%02d",
4685 tm->tm_hour, tm->tm_min, tm->tm_sec);
4686 else if (uptime1 < ONE_WEEK_SECOND)
4687 snprintf (buf, len, "%dd%02dh%02dm",
4688 tm->tm_yday, tm->tm_hour, tm->tm_min);
4689 else
4690 snprintf (buf, len, "%02dw%dd%02dh",
4691 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4692 return buf;
4693}
4694
paul94f2b392005-06-28 12:44:16 +00004695static void
paul718e3742002-12-13 20:15:29 +00004696bgp_config_write_filter (struct vty *vty, struct peer *peer,
4697 afi_t afi, safi_t safi)
4698{
4699 struct bgp_filter *filter;
4700 struct bgp_filter *gfilter = NULL;
4701 char *addr;
4702 int in = FILTER_IN;
4703 int out = FILTER_OUT;
4704
4705 addr = peer->host;
4706 filter = &peer->filter[afi][safi];
4707 if (peer->af_group[afi][safi])
4708 gfilter = &peer->group->conf->filter[afi][safi];
4709
4710 /* distribute-list. */
4711 if (filter->dlist[in].name)
4712 if (! gfilter || ! gfilter->dlist[in].name
4713 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4714 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4715 filter->dlist[in].name, VTY_NEWLINE);
4716 if (filter->dlist[out].name && ! gfilter)
4717 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4718 filter->dlist[out].name, VTY_NEWLINE);
4719
4720 /* prefix-list. */
4721 if (filter->plist[in].name)
4722 if (! gfilter || ! gfilter->plist[in].name
4723 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4724 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4725 filter->plist[in].name, VTY_NEWLINE);
4726 if (filter->plist[out].name && ! gfilter)
4727 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4728 filter->plist[out].name, VTY_NEWLINE);
4729
4730 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004731 if (filter->map[RMAP_IN].name)
4732 if (! gfilter || ! gfilter->map[RMAP_IN].name
4733 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004734 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004735 filter->map[RMAP_IN].name, VTY_NEWLINE);
4736 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004737 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004738 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4739 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4740 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4741 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4742 if (filter->map[RMAP_EXPORT].name)
4743 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4744 || strcmp (filter->map[RMAP_EXPORT].name,
4745 gfilter->map[RMAP_EXPORT].name) != 0)
4746 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4747 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004748
4749 /* unsuppress-map */
4750 if (filter->usmap.name && ! gfilter)
4751 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4752 filter->usmap.name, VTY_NEWLINE);
4753
4754 /* filter-list. */
4755 if (filter->aslist[in].name)
4756 if (! gfilter || ! gfilter->aslist[in].name
4757 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4758 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4759 filter->aslist[in].name, VTY_NEWLINE);
4760 if (filter->aslist[out].name && ! gfilter)
4761 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4762 filter->aslist[out].name, VTY_NEWLINE);
4763}
4764
4765/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004766static void
paul718e3742002-12-13 20:15:29 +00004767bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4768 struct peer *peer, afi_t afi, safi_t safi)
4769{
paul718e3742002-12-13 20:15:29 +00004770 struct peer *g_peer = NULL;
4771 char buf[SU_ADDRSTRLEN];
4772 char *addr;
4773
paul718e3742002-12-13 20:15:29 +00004774 addr = peer->host;
4775 if (peer_group_active (peer))
4776 g_peer = peer->group->conf;
4777
4778 /************************************
4779 ****** Global to the neighbor ******
4780 ************************************/
4781 if (afi == AFI_IP && safi == SAFI_UNICAST)
4782 {
4783 /* remote-as. */
4784 if (! peer_group_active (peer))
4785 {
4786 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4787 vty_out (vty, " neighbor %s peer-group%s", addr,
4788 VTY_NEWLINE);
4789 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004790 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004791 VTY_NEWLINE);
4792 }
4793 else
4794 {
4795 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004796 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004797 VTY_NEWLINE);
4798 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4799 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4800 peer->group->name, VTY_NEWLINE);
4801 }
4802
4803 /* local-as. */
4804 if (peer->change_local_as)
4805 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004806 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004807 peer->change_local_as,
4808 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004809 " no-prepend" : "",
4810 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4811 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004812
4813 /* Description. */
4814 if (peer->desc)
4815 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4816 VTY_NEWLINE);
4817
4818 /* Shutdown. */
4819 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4820 if (! peer_group_active (peer) ||
4821 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4822 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4823
Paul Jakma0df7c912008-07-21 21:02:49 +00004824 /* Password. */
4825 if (peer->password)
4826 if (!peer_group_active (peer)
4827 || ! g_peer->password
4828 || strcmp (peer->password, g_peer->password) != 0)
4829 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4830 VTY_NEWLINE);
4831
paul718e3742002-12-13 20:15:29 +00004832 /* BGP port. */
4833 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004834 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004835 VTY_NEWLINE);
4836
4837 /* Local interface name. */
4838 if (peer->ifname)
4839 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4840 VTY_NEWLINE);
4841
4842 /* Passive. */
4843 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4844 if (! peer_group_active (peer) ||
4845 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4846 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4847
4848 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004849 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004850 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004851 if (! peer_group_active (peer) ||
4852 g_peer->ttl != peer->ttl)
4853 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4854 VTY_NEWLINE);
4855
Nick Hilliardfa411a22011-03-23 15:33:17 +00004856 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004857 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004858 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004859 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004860 peer->gtsm_hops, VTY_NEWLINE);
4861
hasso6ffd2072005-02-02 14:50:11 +00004862 /* disable-connected-check. */
4863 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004864 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004865 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4866 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004867
4868 /* Update-source. */
4869 if (peer->update_if)
4870 if (! peer_group_active (peer) || ! g_peer->update_if
4871 || strcmp (g_peer->update_if, peer->update_if) != 0)
4872 vty_out (vty, " neighbor %s update-source %s%s", addr,
4873 peer->update_if, VTY_NEWLINE);
4874 if (peer->update_source)
4875 if (! peer_group_active (peer) || ! g_peer->update_source
4876 || sockunion_cmp (g_peer->update_source,
4877 peer->update_source) != 0)
4878 vty_out (vty, " neighbor %s update-source %s%s", addr,
4879 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4880 VTY_NEWLINE);
4881
paul718e3742002-12-13 20:15:29 +00004882 /* advertisement-interval */
4883 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4884 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4885 addr, peer->v_routeadv, VTY_NEWLINE);
4886
4887 /* timers. */
4888 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4889 && ! peer_group_active (peer))
4890 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4891 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4892
4893 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4894 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4895 peer->connect, VTY_NEWLINE);
4896
4897 /* Default weight. */
4898 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4899 if (! peer_group_active (peer) ||
4900 g_peer->weight != peer->weight)
4901 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4902 VTY_NEWLINE);
4903
paul718e3742002-12-13 20:15:29 +00004904 /* Dynamic capability. */
4905 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4906 if (! peer_group_active (peer) ||
4907 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4908 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4909 VTY_NEWLINE);
4910
4911 /* dont capability negotiation. */
4912 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4913 if (! peer_group_active (peer) ||
4914 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4915 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4916 VTY_NEWLINE);
4917
4918 /* override capability negotiation. */
4919 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4920 if (! peer_group_active (peer) ||
4921 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4922 vty_out (vty, " neighbor %s override-capability%s", addr,
4923 VTY_NEWLINE);
4924
4925 /* strict capability negotiation. */
4926 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4927 if (! peer_group_active (peer) ||
4928 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4929 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4930 VTY_NEWLINE);
4931
Christian Franke15c71342012-11-19 11:17:31 +00004932 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004933 {
4934 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4935 {
4936 if (peer->afc[AFI_IP][SAFI_UNICAST])
4937 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4938 }
4939 else
4940 {
4941 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4942 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4943 }
4944 }
4945 }
4946
4947
4948 /************************************
4949 ****** Per AF to the neighbor ******
4950 ************************************/
4951
4952 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4953 {
4954 if (peer->af_group[afi][safi])
4955 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4956 peer->group->name, VTY_NEWLINE);
4957 else
4958 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4959 }
4960
4961 /* ORF capability. */
4962 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4963 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4964 if (! peer->af_group[afi][safi])
4965 {
4966 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4967
4968 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4969 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4970 vty_out (vty, " both");
4971 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4972 vty_out (vty, " send");
4973 else
4974 vty_out (vty, " receive");
4975 vty_out (vty, "%s", VTY_NEWLINE);
4976 }
4977
4978 /* Route reflector client. */
4979 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4980 && ! peer->af_group[afi][safi])
4981 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4982 VTY_NEWLINE);
4983
4984 /* Nexthop self. */
4985 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4986 && ! peer->af_group[afi][safi])
4987 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4988
4989 /* Remove private AS. */
4990 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4991 && ! peer->af_group[afi][safi])
4992 vty_out (vty, " neighbor %s remove-private-AS%s",
4993 addr, VTY_NEWLINE);
4994
4995 /* send-community print. */
4996 if (! peer->af_group[afi][safi])
4997 {
4998 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4999 {
5000 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5001 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5002 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5003 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5004 vty_out (vty, " neighbor %s send-community extended%s",
5005 addr, VTY_NEWLINE);
5006 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5007 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5008 }
5009 else
5010 {
5011 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5012 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5013 vty_out (vty, " no neighbor %s send-community both%s",
5014 addr, VTY_NEWLINE);
5015 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5016 vty_out (vty, " no neighbor %s send-community extended%s",
5017 addr, VTY_NEWLINE);
5018 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5019 vty_out (vty, " no neighbor %s send-community%s",
5020 addr, VTY_NEWLINE);
5021 }
5022 }
5023
5024 /* Default information */
5025 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5026 && ! peer->af_group[afi][safi])
5027 {
5028 vty_out (vty, " neighbor %s default-originate", addr);
5029 if (peer->default_rmap[afi][safi].name)
5030 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5031 vty_out (vty, "%s", VTY_NEWLINE);
5032 }
5033
5034 /* Soft reconfiguration inbound. */
5035 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5036 if (! peer->af_group[afi][safi] ||
5037 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5038 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5039 VTY_NEWLINE);
5040
5041 /* maximum-prefix. */
5042 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5043 if (! peer->af_group[afi][safi]
5044 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005045 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005046 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5047 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005048 {
hasso0a486e52005-02-01 20:57:17 +00005049 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5050 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5051 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5052 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5053 vty_out (vty, " warning-only");
5054 if (peer->pmax_restart[afi][safi])
5055 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5056 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005057 }
paul718e3742002-12-13 20:15:29 +00005058
5059 /* Route server client. */
5060 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5061 && ! peer->af_group[afi][safi])
5062 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5063
Dylan Hall3cf12882011-10-27 15:28:17 +04005064 /* Nexthop-local unchanged. */
5065 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5066 && ! peer->af_group[afi][safi])
5067 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5068
paul718e3742002-12-13 20:15:29 +00005069 /* Allow AS in. */
5070 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5071 if (! peer_group_active (peer)
5072 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5073 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5074 {
5075 if (peer->allowas_in[afi][safi] == 3)
5076 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5077 else
5078 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5079 peer->allowas_in[afi][safi], VTY_NEWLINE);
5080 }
5081
5082 /* Filter. */
5083 bgp_config_write_filter (vty, peer, afi, safi);
5084
5085 /* atribute-unchanged. */
5086 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5087 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5088 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5089 && ! peer->af_group[afi][safi])
5090 {
5091 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5092 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5093 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5094 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5095 else
5096 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5097 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5098 " as-path" : "",
5099 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5100 " next-hop" : "",
5101 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5102 " med" : "", VTY_NEWLINE);
5103 }
5104}
5105
5106/* Display "address-family" configuration header. */
5107void
5108bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5109 int *write)
5110{
5111 if (*write)
5112 return;
5113
5114 if (afi == AFI_IP && safi == SAFI_UNICAST)
5115 return;
5116
5117 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5118
5119 if (afi == AFI_IP)
5120 {
5121 if (safi == SAFI_MULTICAST)
5122 vty_out (vty, "ipv4 multicast");
5123 else if (safi == SAFI_MPLS_VPN)
5124 vty_out (vty, "vpnv4 unicast");
5125 }
5126 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005127 {
5128 vty_out (vty, "ipv6");
5129
5130 if (safi == SAFI_MULTICAST)
5131 vty_out (vty, " multicast");
5132 }
paul718e3742002-12-13 20:15:29 +00005133
5134 vty_out (vty, "%s", VTY_NEWLINE);
5135
5136 *write = 1;
5137}
5138
5139/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005140static int
paul718e3742002-12-13 20:15:29 +00005141bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5142 safi_t safi)
5143{
5144 int write = 0;
5145 struct peer *peer;
5146 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005147 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005148
5149 bgp_config_write_network (vty, bgp, afi, safi, &write);
5150
5151 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5152
paul1eb8ef22005-04-07 07:30:20 +00005153 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005154 {
5155 if (group->conf->afc[afi][safi])
5156 {
5157 bgp_config_write_family_header (vty, afi, safi, &write);
5158 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5159 }
5160 }
paul1eb8ef22005-04-07 07:30:20 +00005161 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005162 {
5163 if (peer->afc[afi][safi])
5164 {
5165 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5166 {
5167 bgp_config_write_family_header (vty, afi, safi, &write);
5168 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5169 }
5170 }
5171 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005172
5173 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5174
paul718e3742002-12-13 20:15:29 +00005175 if (write)
5176 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5177
5178 return write;
5179}
5180
5181int
5182bgp_config_write (struct vty *vty)
5183{
5184 int write = 0;
5185 struct bgp *bgp;
5186 struct peer_group *group;
5187 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005188 struct listnode *node, *nnode;
5189 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005190
5191 /* BGP Multiple instance. */
5192 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5193 {
5194 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5195 write++;
5196 }
5197
5198 /* BGP Config type. */
5199 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5200 {
5201 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5202 write++;
5203 }
5204
5205 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005206 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005207 {
5208 if (write)
5209 vty_out (vty, "!%s", VTY_NEWLINE);
5210
5211 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005212 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005213
5214 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5215 {
5216 if (bgp->name)
5217 vty_out (vty, " view %s", bgp->name);
5218 }
5219 vty_out (vty, "%s", VTY_NEWLINE);
5220
5221 /* No Synchronization */
5222 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5223 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5224
5225 /* BGP fast-external-failover. */
5226 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5227 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5228
5229 /* BGP router ID. */
5230 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5231 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5232 VTY_NEWLINE);
5233
paul848973c2003-08-13 00:32:49 +00005234 /* BGP log-neighbor-changes. */
5235 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5236 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5237
paul718e3742002-12-13 20:15:29 +00005238 /* BGP configuration. */
5239 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5240 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5241
5242 /* BGP default ipv4-unicast. */
5243 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5244 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5245
5246 /* BGP default local-preference. */
5247 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5248 vty_out (vty, " bgp default local-preference %d%s",
5249 bgp->default_local_pref, VTY_NEWLINE);
5250
5251 /* BGP client-to-client reflection. */
5252 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5253 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5254
5255 /* BGP cluster ID. */
5256 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5257 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5258 VTY_NEWLINE);
5259
hassoe0701b72004-05-20 09:19:34 +00005260 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005261 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005262 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5263 VTY_NEWLINE);
5264
5265 /* Confederation peer */
5266 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005267 {
hassoe0701b72004-05-20 09:19:34 +00005268 int i;
paul718e3742002-12-13 20:15:29 +00005269
hassoe0701b72004-05-20 09:19:34 +00005270 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005271
hassoe0701b72004-05-20 09:19:34 +00005272 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005273 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005274
hassoe0701b72004-05-20 09:19:34 +00005275 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005276 }
5277
5278 /* BGP enforce-first-as. */
5279 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5280 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5281
5282 /* BGP deterministic-med. */
5283 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5284 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005285
5286 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005287 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5288 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5289 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005290 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5291 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5292
paul718e3742002-12-13 20:15:29 +00005293 /* BGP bestpath method. */
5294 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5295 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005296 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5297 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005298 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5299 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5300 }
paul718e3742002-12-13 20:15:29 +00005301 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5302 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5303 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5304 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5305 {
5306 vty_out (vty, " bgp bestpath med");
5307 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5308 vty_out (vty, " confed");
5309 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5310 vty_out (vty, " missing-as-worst");
5311 vty_out (vty, "%s", VTY_NEWLINE);
5312 }
5313
5314 /* BGP network import check. */
5315 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5316 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5317
5318 /* BGP scan interval. */
5319 bgp_config_write_scan_time (vty);
5320
5321 /* BGP flag dampening. */
5322 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5323 BGP_CONFIG_DAMPENING))
5324 bgp_config_write_damp (vty);
5325
5326 /* BGP static route configuration. */
5327 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5328
5329 /* BGP redistribute configuration. */
5330 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5331
5332 /* BGP timers configuration. */
5333 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5334 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5335 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5336 bgp->default_holdtime, VTY_NEWLINE);
5337
5338 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005339 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005340 {
5341 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5342 }
5343
5344 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005345 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005346 {
5347 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5348 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5349 }
5350
Josh Bailey165b5ff2011-07-20 20:43:22 -07005351 /* maximum-paths */
5352 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5353
paul718e3742002-12-13 20:15:29 +00005354 /* Distance configuration. */
5355 bgp_config_write_distance (vty, bgp);
5356
5357 /* No auto-summary */
5358 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5359 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5360
5361 /* IPv4 multicast configuration. */
5362 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5363
5364 /* IPv4 VPN configuration. */
5365 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5366
5367 /* IPv6 unicast configuration. */
5368 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5369
Paul Jakma37a217a2007-04-10 19:20:29 +00005370 /* IPv6 multicast configuration. */
5371 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5372
paul718e3742002-12-13 20:15:29 +00005373 write++;
5374 }
5375 return write;
5376}
5377
5378void
paul94f2b392005-06-28 12:44:16 +00005379bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005380{
5381 memset (&bgp_master, 0, sizeof (struct bgp_master));
5382
5383 bm = &bgp_master;
5384 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005385 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005386 bm->port = BGP_PORT_DEFAULT;
5387 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005388 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005389}
paul200df112005-06-01 11:17:05 +00005390
paul718e3742002-12-13 20:15:29 +00005391
5392void
paul94f2b392005-06-28 12:44:16 +00005393bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005394{
paul718e3742002-12-13 20:15:29 +00005395 /* BGP VTY commands installation. */
5396 bgp_vty_init ();
5397
paul718e3742002-12-13 20:15:29 +00005398 /* Init zebra. */
5399 bgp_zebra_init ();
5400
5401 /* BGP inits. */
5402 bgp_attr_init ();
5403 bgp_debug_init ();
5404 bgp_dump_init ();
5405 bgp_route_init ();
5406 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005407 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005408 bgp_scan_init ();
5409 bgp_mplsvpn_init ();
5410
5411 /* Access list initialize. */
5412 access_list_init ();
5413 access_list_add_hook (peer_distribute_update);
5414 access_list_delete_hook (peer_distribute_update);
5415
5416 /* Filter list initialize. */
5417 bgp_filter_init ();
5418 as_list_add_hook (peer_aslist_update);
5419 as_list_delete_hook (peer_aslist_update);
5420
5421 /* Prefix list initialize.*/
5422 prefix_list_init ();
5423 prefix_list_add_hook (peer_prefix_list_update);
5424 prefix_list_delete_hook (peer_prefix_list_update);
5425
5426 /* Community list initialize. */
5427 bgp_clist = community_list_init ();
5428
5429#ifdef HAVE_SNMP
5430 bgp_snmp_init ();
5431#endif /* HAVE_SNMP */
5432}
paul545acaf2004-04-20 15:13:15 +00005433
5434void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005435bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005436{
paul545acaf2004-04-20 15:13:15 +00005437 struct bgp *bgp;
5438 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005439 struct listnode *node, *nnode;
5440 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005441
paul1eb8ef22005-04-07 07:30:20 +00005442 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5443 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005444 if (peer->status == Established)
5445 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5446 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005447
paul545acaf2004-04-20 15:13:15 +00005448 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005449
paule210cf92005-06-15 19:15:35 +00005450 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005451 {
5452 work_queue_free (bm->process_main_queue);
5453 bm->process_main_queue = NULL;
5454 }
paule210cf92005-06-15 19:15:35 +00005455 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005456 {
5457 work_queue_free (bm->process_rsclient_queue);
5458 bm->process_rsclient_queue = NULL;
5459 }
paul545acaf2004-04-20 15:13:15 +00005460}