blob: 6a21b11abc02525b751b36da7473645443872ede [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);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000835 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000836
837 bgp_sync_init (peer);
838
839 /* Get service port number. */
840 sp = getservbyname ("bgp", "tcp");
841 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
842
843 return peer;
844}
845
846/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000847static struct peer *
paul718e3742002-12-13 20:15:29 +0000848peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
849 as_t remote_as, afi_t afi, safi_t safi)
850{
851 int active;
852 struct peer *peer;
853 char buf[SU_ADDRSTRLEN];
854
Paul Jakma6f585442006-10-22 19:13:07 +0000855 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000856 peer->su = *su;
857 peer->local_as = local_as;
858 peer->as = remote_as;
859 peer->local_id = bgp->router_id;
860 peer->v_holdtime = bgp->default_holdtime;
861 peer->v_keepalive = bgp->default_keepalive;
862 if (peer_sort (peer) == BGP_PEER_IBGP)
863 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
864 else
865 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000866
867 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000868 listnode_add_sort (bgp->peer, peer);
869
870 active = peer_active (peer);
871
872 if (afi && safi)
873 peer->afc[afi][safi] = 1;
874
Stephen Hemminger65957882010-01-15 16:22:10 +0300875 /* Last read and reset time set */
876 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000877
paul718e3742002-12-13 20:15:29 +0000878 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000879 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000880
881 /* Make peer's address string. */
882 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000883 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000884
885 /* Set up peer's events and timers. */
886 if (! active && peer_active (peer))
887 bgp_timer_set (peer);
888
889 return peer;
890}
891
pauleb821182004-05-01 08:44:08 +0000892/* Make accept BGP peer. Called from bgp_accept (). */
893struct peer *
894peer_create_accept (struct bgp *bgp)
895{
896 struct peer *peer;
897
Paul Jakma6f585442006-10-22 19:13:07 +0000898 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000899
900 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000901 listnode_add_sort (bgp->peer, peer);
902
903 return peer;
904}
905
paul718e3742002-12-13 20:15:29 +0000906/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000907static void
paul718e3742002-12-13 20:15:29 +0000908peer_as_change (struct peer *peer, as_t as)
909{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000910 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000911
912 /* Stop peer. */
913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
914 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000915 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000916 {
917 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
920 }
paul718e3742002-12-13 20:15:29 +0000921 else
922 BGP_EVENT_ADD (peer, BGP_Stop);
923 }
924 type = peer_sort (peer);
925 peer->as = as;
926
paul848973c2003-08-13 00:32:49 +0000927 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
928 && ! bgp_confederation_peers_check (peer->bgp, as)
929 && peer->bgp->as != as)
930 peer->local_as = peer->bgp->confed_id;
931 else
932 peer->local_as = peer->bgp->as;
933
paul718e3742002-12-13 20:15:29 +0000934 /* Advertisement-interval reset */
935 if (peer_sort (peer) == BGP_PEER_IBGP)
936 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
937 else
938 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
939
940 /* TTL reset */
941 if (peer_sort (peer) == BGP_PEER_IBGP)
942 peer->ttl = 255;
943 else if (type == BGP_PEER_IBGP)
944 peer->ttl = 1;
945
946 /* reflector-client reset */
947 if (peer_sort (peer) != BGP_PEER_IBGP)
948 {
949 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
950 PEER_FLAG_REFLECTOR_CLIENT);
951 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
952 PEER_FLAG_REFLECTOR_CLIENT);
953 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
954 PEER_FLAG_REFLECTOR_CLIENT);
955 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
956 PEER_FLAG_REFLECTOR_CLIENT);
957 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
958 PEER_FLAG_REFLECTOR_CLIENT);
959 }
960
961 /* local-as reset */
962 if (peer_sort (peer) != BGP_PEER_EBGP)
963 {
964 peer->change_local_as = 0;
965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000966 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000967 }
968}
969
970/* If peer does not exist, create new one. If peer already exists,
971 set AS number to the peer. */
972int
973peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
974 afi_t afi, safi_t safi)
975{
976 struct peer *peer;
977 as_t local_as;
978
979 peer = peer_lookup (bgp, su);
980
981 if (peer)
982 {
983 /* When this peer is a member of peer-group. */
984 if (peer->group)
985 {
986 if (peer->group->conf->as)
987 {
988 /* Return peer group's AS number. */
989 *as = peer->group->conf->as;
990 return BGP_ERR_PEER_GROUP_MEMBER;
991 }
992 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
993 {
994 if (bgp->as != *as)
995 {
996 *as = peer->as;
997 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
998 }
999 }
1000 else
1001 {
1002 if (bgp->as == *as)
1003 {
1004 *as = peer->as;
1005 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1006 }
1007 }
1008 }
1009
1010 /* Existing peer's AS number change. */
1011 if (peer->as != *as)
1012 peer_as_change (peer, *as);
1013 }
1014 else
1015 {
1016
1017 /* If the peer is not part of our confederation, and its not an
1018 iBGP peer then spoof the source AS */
1019 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1020 && ! bgp_confederation_peers_check (bgp, *as)
1021 && bgp->as != *as)
1022 local_as = bgp->confed_id;
1023 else
1024 local_as = bgp->as;
1025
1026 /* If this is IPv4 unicast configuration and "no bgp default
1027 ipv4-unicast" is specified. */
1028
1029 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1030 && afi == AFI_IP && safi == SAFI_UNICAST)
1031 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1032 else
1033 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1034 }
1035
1036 return 0;
1037}
1038
1039/* Activate the peer or peer group for specified AFI and SAFI. */
1040int
1041peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1042{
1043 int active;
1044
1045 if (peer->afc[afi][safi])
1046 return 0;
1047
1048 /* Activate the address family configuration. */
1049 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1050 peer->afc[afi][safi] = 1;
1051 else
1052 {
1053 active = peer_active (peer);
1054
1055 peer->afc[afi][safi] = 1;
1056
1057 if (! active && peer_active (peer))
1058 bgp_timer_set (peer);
1059 else
1060 {
1061 if (peer->status == Established)
1062 {
1063 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1064 {
1065 peer->afc_adv[afi][safi] = 1;
1066 bgp_capability_send (peer, afi, safi,
1067 CAPABILITY_CODE_MP,
1068 CAPABILITY_ACTION_SET);
1069 if (peer->afc_recv[afi][safi])
1070 {
1071 peer->afc_nego[afi][safi] = 1;
1072 bgp_announce_route (peer, afi, safi);
1073 }
1074 }
1075 else
hassoe0701b72004-05-20 09:19:34 +00001076 {
1077 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1078 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1079 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1080 }
paul718e3742002-12-13 20:15:29 +00001081 }
1082 }
1083 }
1084 return 0;
1085}
1086
1087int
1088peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1089{
1090 struct peer_group *group;
1091 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001093
1094 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1095 {
1096 group = peer->group;
1097
paul1eb8ef22005-04-07 07:30:20 +00001098 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001099 {
1100 if (peer1->af_group[afi][safi])
1101 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1102 }
1103 }
1104 else
1105 {
1106 if (peer->af_group[afi][safi])
1107 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1108 }
1109
1110 if (! peer->afc[afi][safi])
1111 return 0;
1112
1113 /* De-activate the address family configuration. */
1114 peer->afc[afi][safi] = 0;
1115 peer_af_flag_reset (peer, afi, safi);
1116
1117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1118 {
1119 if (peer->status == Established)
1120 {
1121 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1122 {
1123 peer->afc_adv[afi][safi] = 0;
1124 peer->afc_nego[afi][safi] = 0;
1125
1126 if (peer_active_nego (peer))
1127 {
1128 bgp_capability_send (peer, afi, safi,
1129 CAPABILITY_CODE_MP,
1130 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001131 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001132 peer->pcount[afi][safi] = 0;
1133 }
1134 else
hassoe0701b72004-05-20 09:19:34 +00001135 {
1136 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1137 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1138 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1139 }
paul718e3742002-12-13 20:15:29 +00001140 }
1141 else
hassoe0701b72004-05-20 09:19:34 +00001142 {
1143 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1144 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1145 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1146 }
paul718e3742002-12-13 20:15:29 +00001147 }
1148 }
1149 return 0;
1150}
1151
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001152static void
hasso93406d82005-02-02 14:40:33 +00001153peer_nsf_stop (struct peer *peer)
1154{
1155 afi_t afi;
1156 safi_t safi;
1157
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1159 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1160
1161 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001162 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001163 peer->nsf[afi][safi] = 0;
1164
1165 if (peer->t_gr_restart)
1166 {
1167 BGP_TIMER_OFF (peer->t_gr_restart);
1168 if (BGP_DEBUG (events, EVENTS))
1169 zlog_debug ("%s graceful restart timer stopped", peer->host);
1170 }
1171 if (peer->t_gr_stale)
1172 {
1173 BGP_TIMER_OFF (peer->t_gr_stale);
1174 if (BGP_DEBUG (events, EVENTS))
1175 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1176 }
1177 bgp_clear_route_all (peer);
1178}
1179
Paul Jakmaca058a32006-09-14 02:58:49 +00001180/* Delete peer from confguration.
1181 *
1182 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1183 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1184 *
1185 * This function /should/ take care to be idempotent, to guard against
1186 * it being called multiple times through stray events that come in
1187 * that happen to result in this function being called again. That
1188 * said, getting here for a "Deleted" peer is a bug in the neighbour
1189 * FSM.
1190 */
paul718e3742002-12-13 20:15:29 +00001191int
1192peer_delete (struct peer *peer)
1193{
1194 int i;
1195 afi_t afi;
1196 safi_t safi;
1197 struct bgp *bgp;
1198 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001199 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001200
Paul Jakmaca058a32006-09-14 02:58:49 +00001201 assert (peer->status != Deleted);
1202
paul718e3742002-12-13 20:15:29 +00001203 bgp = peer->bgp;
1204
hasso93406d82005-02-02 14:40:33 +00001205 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1206 peer_nsf_stop (peer);
1207
Chris Caputo228da422009-07-18 05:44:03 +00001208 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001209 relationship. */
1210 if (peer->group)
1211 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001212 if ((pn = listnode_lookup (peer->group->peer, peer)))
1213 {
1214 peer = peer_unlock (peer); /* group->peer list reference */
1215 list_delete_node (peer->group->peer, pn);
1216 }
paul718e3742002-12-13 20:15:29 +00001217 peer->group = NULL;
1218 }
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001221 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1222 * executed after peer structure is deleted.
1223 */
hassoe0701b72004-05-20 09:19:34 +00001224 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001225 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001227
1228 /* Password configuration */
1229 if (peer->password)
1230 {
1231 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1232 peer->password = NULL;
1233
1234 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1235 bgp_md5_set (peer);
1236 }
1237
Paul Jakmaca058a32006-09-14 02:58:49 +00001238 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001239
paul718e3742002-12-13 20:15:29 +00001240 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1242 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001243 {
Chris Caputo228da422009-07-18 05:44:03 +00001244 peer_unlock (peer); /* bgp peer list reference */
1245 list_delete_node (bgp->peer, pn);
1246 }
paul200df112005-06-01 11:17:05 +00001247
Chris Caputo228da422009-07-18 05:44:03 +00001248 if (peer_rsclient_active (peer)
1249 && (pn = listnode_lookup (bgp->rsclient, peer)))
1250 {
1251 peer_unlock (peer); /* rsclient list reference */
1252 list_delete_node (bgp->rsclient, pn);
1253
1254 /* Clear our own rsclient ribs. */
1255 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1256 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1257 if (CHECK_FLAG(peer->af_flags[afi][safi],
1258 PEER_FLAG_RSERVER_CLIENT))
1259 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001260 }
1261
1262 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1263 member of a peer_group. */
1264 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1265 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1266 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001267 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001268
paul200df112005-06-01 11:17:05 +00001269 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001270 if (peer->ibuf)
1271 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001272 if (peer->obuf)
1273 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001274 if (peer->work)
1275 stream_free (peer->work);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001276 if (peer->scratch)
1277 stream_free(peer->scratch);
Paul Jakma18937402006-07-27 19:05:12 +00001278 peer->obuf = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001279 peer->work = peer->scratch = peer->ibuf = NULL;
Paul Jakma18937402006-07-27 19:05:12 +00001280
paul718e3742002-12-13 20:15:29 +00001281 /* Local and remote addresses. */
1282 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001283 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001284 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001285 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001286 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001287
paul718e3742002-12-13 20:15:29 +00001288 /* Free filter related memory. */
1289 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1290 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1291 {
1292 filter = &peer->filter[afi][safi];
1293
1294 for (i = FILTER_IN; i < FILTER_MAX; i++)
1295 {
1296 if (filter->dlist[i].name)
1297 free (filter->dlist[i].name);
1298 if (filter->plist[i].name)
1299 free (filter->plist[i].name);
1300 if (filter->aslist[i].name)
1301 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001302
1303 filter->dlist[i].name = NULL;
1304 filter->plist[i].name = NULL;
1305 filter->aslist[i].name = NULL;
1306 }
1307 for (i = RMAP_IN; i < RMAP_MAX; i++)
1308 {
paul718e3742002-12-13 20:15:29 +00001309 if (filter->map[i].name)
1310 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001311 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001312 }
1313
1314 if (filter->usmap.name)
1315 free (filter->usmap.name);
1316
1317 if (peer->default_rmap[afi][safi].name)
1318 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001319
1320 filter->usmap.name = NULL;
1321 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001322 }
paul200df112005-06-01 11:17:05 +00001323
1324 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001325
1326 return 0;
1327}
1328
paul94f2b392005-06-28 12:44:16 +00001329static int
paul718e3742002-12-13 20:15:29 +00001330peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1331{
1332 return strcmp (g1->name, g2->name);
1333}
1334
1335/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001336static int
paul718e3742002-12-13 20:15:29 +00001337peer_group_active (struct peer *peer)
1338{
1339 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1340 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1341 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1342 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1343 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1344 return 1;
1345 return 0;
1346}
1347
1348/* Peer group cofiguration. */
1349static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001350peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001351{
1352 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1353 sizeof (struct peer_group));
1354}
1355
paul94f2b392005-06-28 12:44:16 +00001356static void
paul718e3742002-12-13 20:15:29 +00001357peer_group_free (struct peer_group *group)
1358{
1359 XFREE (MTYPE_PEER_GROUP, group);
1360}
1361
1362struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001363peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001367
paul1eb8ef22005-04-07 07:30:20 +00001368 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001369 {
1370 if (strcmp (group->name, name) == 0)
1371 return group;
1372 }
1373 return NULL;
1374}
1375
1376struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001377peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001378{
1379 struct peer_group *group;
1380
1381 group = peer_group_lookup (bgp, name);
1382 if (group)
1383 return group;
1384
1385 group = peer_group_new ();
1386 group->bgp = bgp;
1387 group->name = strdup (name);
1388 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001389 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001390 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1391 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001392 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001393 group->conf->group = group;
1394 group->conf->as = 0;
1395 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001396 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001397 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1398 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1399 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1400 group->conf->keepalive = 0;
1401 group->conf->holdtime = 0;
1402 group->conf->connect = 0;
1403 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1404 listnode_add_sort (bgp->group, group);
1405
1406 return 0;
1407}
1408
paul94f2b392005-06-28 12:44:16 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1411 afi_t afi, safi_t safi)
1412{
1413 int in = FILTER_IN;
1414 int out = FILTER_OUT;
1415 struct peer *conf;
1416 struct bgp_filter *pfilter;
1417 struct bgp_filter *gfilter;
1418
1419 conf = group->conf;
1420 pfilter = &peer->filter[afi][safi];
1421 gfilter = &conf->filter[afi][safi];
1422
1423 /* remote-as */
1424 if (conf->as)
1425 peer->as = conf->as;
1426
1427 /* remote-as */
1428 if (conf->change_local_as)
1429 peer->change_local_as = conf->change_local_as;
1430
1431 /* TTL */
1432 peer->ttl = conf->ttl;
1433
Nick Hilliardfa411a22011-03-23 15:33:17 +00001434 /* GTSM hops */
1435 peer->gtsm_hops = conf->gtsm_hops;
1436
paul718e3742002-12-13 20:15:29 +00001437 /* Weight */
1438 peer->weight = conf->weight;
1439
1440 /* peer flags apply */
1441 peer->flags = conf->flags;
1442 /* peer af_flags apply */
1443 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1444 /* peer config apply */
1445 peer->config = conf->config;
1446
1447 /* peer timers apply */
1448 peer->holdtime = conf->holdtime;
1449 peer->keepalive = conf->keepalive;
1450 peer->connect = conf->connect;
1451 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1452 peer->v_connect = conf->connect;
1453 else
1454 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1455
1456 /* advertisement-interval reset */
1457 if (peer_sort (peer) == BGP_PEER_IBGP)
1458 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1459 else
1460 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1461
Paul Jakma0df7c912008-07-21 21:02:49 +00001462 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001463 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001464 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001465
1466 bgp_md5_set (peer);
1467
paul718e3742002-12-13 20:15:29 +00001468 /* maximum-prefix */
1469 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001470 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001471 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001472
1473 /* allowas-in */
1474 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1475
paulfee0f4c2004-09-13 05:12:46 +00001476 /* route-server-client */
1477 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1478 {
1479 /* Make peer's RIB point to group's RIB. */
1480 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1481
1482 /* Import policy. */
1483 if (pfilter->map[RMAP_IMPORT].name)
1484 free (pfilter->map[RMAP_IMPORT].name);
1485 if (gfilter->map[RMAP_IMPORT].name)
1486 {
1487 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1488 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1489 }
1490 else
1491 {
1492 pfilter->map[RMAP_IMPORT].name = NULL;
1493 pfilter->map[RMAP_IMPORT].map = NULL;
1494 }
1495
1496 /* Export policy. */
1497 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1498 {
1499 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1500 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1501 }
1502 }
1503
paul718e3742002-12-13 20:15:29 +00001504 /* default-originate route-map */
1505 if (conf->default_rmap[afi][safi].name)
1506 {
1507 if (peer->default_rmap[afi][safi].name)
1508 free (peer->default_rmap[afi][safi].name);
1509 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1510 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1511 }
1512
1513 /* update-source apply */
1514 if (conf->update_source)
1515 {
1516 if (peer->update_source)
1517 sockunion_free (peer->update_source);
1518 if (peer->update_if)
1519 {
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 peer->update_if = NULL;
1522 }
1523 peer->update_source = sockunion_dup (conf->update_source);
1524 }
1525 else if (conf->update_if)
1526 {
1527 if (peer->update_if)
1528 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1529 if (peer->update_source)
1530 {
1531 sockunion_free (peer->update_source);
1532 peer->update_source = NULL;
1533 }
1534 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1535 }
1536
1537 /* inbound filter apply */
1538 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1539 {
1540 if (pfilter->dlist[in].name)
1541 free (pfilter->dlist[in].name);
1542 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1543 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1544 }
1545 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1546 {
1547 if (pfilter->plist[in].name)
1548 free (pfilter->plist[in].name);
1549 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1550 pfilter->plist[in].plist = gfilter->plist[in].plist;
1551 }
1552 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1553 {
1554 if (pfilter->aslist[in].name)
1555 free (pfilter->aslist[in].name);
1556 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1557 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1558 }
paulfee0f4c2004-09-13 05:12:46 +00001559 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001560 {
paulfee0f4c2004-09-13 05:12:46 +00001561 if (pfilter->map[RMAP_IN].name)
1562 free (pfilter->map[RMAP_IN].name);
1563 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1564 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001565 }
1566
1567 /* outbound filter apply */
1568 if (gfilter->dlist[out].name)
1569 {
1570 if (pfilter->dlist[out].name)
1571 free (pfilter->dlist[out].name);
1572 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1573 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1574 }
1575 else
1576 {
1577 if (pfilter->dlist[out].name)
1578 free (pfilter->dlist[out].name);
1579 pfilter->dlist[out].name = NULL;
1580 pfilter->dlist[out].alist = NULL;
1581 }
1582 if (gfilter->plist[out].name)
1583 {
1584 if (pfilter->plist[out].name)
1585 free (pfilter->plist[out].name);
1586 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1587 pfilter->plist[out].plist = gfilter->plist[out].plist;
1588 }
1589 else
1590 {
1591 if (pfilter->plist[out].name)
1592 free (pfilter->plist[out].name);
1593 pfilter->plist[out].name = NULL;
1594 pfilter->plist[out].plist = NULL;
1595 }
1596 if (gfilter->aslist[out].name)
1597 {
1598 if (pfilter->aslist[out].name)
1599 free (pfilter->aslist[out].name);
1600 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1601 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1602 }
1603 else
1604 {
1605 if (pfilter->aslist[out].name)
1606 free (pfilter->aslist[out].name);
1607 pfilter->aslist[out].name = NULL;
1608 pfilter->aslist[out].aslist = NULL;
1609 }
paulfee0f4c2004-09-13 05:12:46 +00001610 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001611 {
paulfee0f4c2004-09-13 05:12:46 +00001612 if (pfilter->map[RMAP_OUT].name)
1613 free (pfilter->map[RMAP_OUT].name);
1614 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1615 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001616 }
1617 else
1618 {
paulfee0f4c2004-09-13 05:12:46 +00001619 if (pfilter->map[RMAP_OUT].name)
1620 free (pfilter->map[RMAP_OUT].name);
1621 pfilter->map[RMAP_OUT].name = NULL;
1622 pfilter->map[RMAP_OUT].map = NULL;
1623 }
1624
1625 /* RS-client's import/export route-maps. */
1626 if (gfilter->map[RMAP_IMPORT].name)
1627 {
1628 if (pfilter->map[RMAP_IMPORT].name)
1629 free (pfilter->map[RMAP_IMPORT].name);
1630 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1631 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1632 }
1633 else
1634 {
1635 if (pfilter->map[RMAP_IMPORT].name)
1636 free (pfilter->map[RMAP_IMPORT].name);
1637 pfilter->map[RMAP_IMPORT].name = NULL;
1638 pfilter->map[RMAP_IMPORT].map = NULL;
1639 }
1640 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1641 {
1642 if (pfilter->map[RMAP_EXPORT].name)
1643 free (pfilter->map[RMAP_EXPORT].name);
1644 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1645 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001646 }
1647
1648 if (gfilter->usmap.name)
1649 {
1650 if (pfilter->usmap.name)
1651 free (pfilter->usmap.name);
1652 pfilter->usmap.name = strdup (gfilter->usmap.name);
1653 pfilter->usmap.map = gfilter->usmap.map;
1654 }
1655 else
1656 {
1657 if (pfilter->usmap.name)
1658 free (pfilter->usmap.name);
1659 pfilter->usmap.name = NULL;
1660 pfilter->usmap.map = NULL;
1661 }
1662}
1663
1664/* Peer group's remote AS configuration. */
1665int
paulfd79ac92004-10-13 05:06:08 +00001666peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001667{
1668 struct peer_group *group;
1669 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001670 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001671
1672 group = peer_group_lookup (bgp, group_name);
1673 if (! group)
1674 return -1;
1675
1676 if (group->conf->as == *as)
1677 return 0;
1678
1679 /* When we setup peer-group AS number all peer group member's AS
1680 number must be updated to same number. */
1681 peer_as_change (group->conf, *as);
1682
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001684 {
1685 if (peer->as != *as)
1686 peer_as_change (peer, *as);
1687 }
1688
1689 return 0;
1690}
1691
1692int
1693peer_group_delete (struct peer_group *group)
1694{
1695 struct bgp *bgp;
1696 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001697 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001698
1699 bgp = group->bgp;
1700
paul1eb8ef22005-04-07 07:30:20 +00001701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001702 {
1703 peer->group = NULL;
1704 peer_delete (peer);
1705 }
1706 list_delete (group->peer);
1707
1708 free (group->name);
1709 group->name = NULL;
1710
1711 group->conf->group = NULL;
1712 peer_delete (group->conf);
1713
1714 /* Delete from all peer_group list. */
1715 listnode_delete (bgp->group, group);
1716
1717 peer_group_free (group);
1718
1719 return 0;
1720}
1721
1722int
1723peer_group_remote_as_delete (struct peer_group *group)
1724{
1725 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001727
1728 if (! group->conf->as)
1729 return 0;
1730
paul1eb8ef22005-04-07 07:30:20 +00001731 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001732 {
1733 peer->group = NULL;
1734 peer_delete (peer);
1735 }
1736 list_delete_all_node (group->peer);
1737
1738 group->conf->as = 0;
1739
1740 return 0;
1741}
1742
1743/* Bind specified peer to peer group. */
1744int
1745peer_group_bind (struct bgp *bgp, union sockunion *su,
1746 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1747{
1748 struct peer *peer;
1749 int first_member = 0;
1750
1751 /* Check peer group's address family. */
1752 if (! group->conf->afc[afi][safi])
1753 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1754
1755 /* Lookup the peer. */
1756 peer = peer_lookup (bgp, su);
1757
1758 /* Create a new peer. */
1759 if (! peer)
1760 {
1761 if (! group->conf->as)
1762 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1763
1764 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1765 peer->group = group;
1766 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001767
Paul Jakmaca058a32006-09-14 02:58:49 +00001768 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001769 listnode_add (group->peer, peer);
1770 peer_group2peer_config_copy (group, peer, afi, safi);
1771
1772 return 0;
1773 }
1774
1775 /* When the peer already belongs to peer group, check the consistency. */
1776 if (peer->af_group[afi][safi])
1777 {
1778 if (strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1780
1781 return 0;
1782 }
1783
1784 /* Check current peer group configuration. */
1785 if (peer_group_active (peer)
1786 && strcmp (peer->group->name, group->name) != 0)
1787 return BGP_ERR_PEER_GROUP_MISMATCH;
1788
1789 if (! group->conf->as)
1790 {
1791 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1792 && peer_sort (group->conf) != peer_sort (peer))
1793 {
1794 if (as)
1795 *as = peer->as;
1796 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1797 }
1798
1799 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1800 first_member = 1;
1801 }
1802
1803 peer->af_group[afi][safi] = 1;
1804 peer->afc[afi][safi] = 1;
1805 if (! peer->group)
1806 {
1807 peer->group = group;
paul200df112005-06-01 11:17:05 +00001808
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001810 listnode_add (group->peer, peer);
1811 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 else
1813 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001814
1815 if (first_member)
1816 {
1817 /* Advertisement-interval reset */
1818 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1819 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1820 else
1821 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1822
1823 /* ebgp-multihop reset */
1824 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1825 group->conf->ttl = 255;
1826
1827 /* local-as reset */
1828 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1829 {
1830 group->conf->change_local_as = 0;
1831 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001832 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001833 }
1834 }
paulfee0f4c2004-09-13 05:12:46 +00001835
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1837 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 struct listnode *pn;
1839
paulfee0f4c2004-09-13 05:12:46 +00001840 /* If it's not configured as RSERVER_CLIENT in any other address
1841 family, without being member of a peer_group, remove it from
1842 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001843 if (! peer_rsclient_active (peer)
1844 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001845 {
1846 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001847 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001848
1849 /* Clear our own rsclient rib for this afi/safi. */
1850 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001851 }
paulfee0f4c2004-09-13 05:12:46 +00001852
Paul Jakmab608d5b2008-07-02 02:12:07 +00001853 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001854
1855 /* Import policy. */
1856 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1859 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1861 }
1862
1863 /* Export policy. */
1864 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1865 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1866 {
1867 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1868 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1869 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1870 }
1871 }
1872
paul718e3742002-12-13 20:15:29 +00001873 peer_group2peer_config_copy (group, peer, afi, safi);
1874
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001875 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001876 {
1877 peer->last_reset = PEER_DOWN_RMAP_BIND;
1878 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1879 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1880 }
paul718e3742002-12-13 20:15:29 +00001881 else
1882 BGP_EVENT_ADD (peer, BGP_Stop);
1883
1884 return 0;
1885}
1886
1887int
1888peer_group_unbind (struct bgp *bgp, struct peer *peer,
1889 struct peer_group *group, afi_t afi, safi_t safi)
1890{
1891 if (! peer->af_group[afi][safi])
1892 return 0;
1893
1894 if (group != peer->group)
1895 return BGP_ERR_PEER_GROUP_MISMATCH;
1896
1897 peer->af_group[afi][safi] = 0;
1898 peer->afc[afi][safi] = 0;
1899 peer_af_flag_reset (peer, afi, safi);
1900
paulfee0f4c2004-09-13 05:12:46 +00001901 if (peer->rib[afi][safi])
1902 peer->rib[afi][safi] = NULL;
1903
paul718e3742002-12-13 20:15:29 +00001904 if (! peer_group_active (peer))
1905 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001906 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001907 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001908 listnode_delete (group->peer, peer);
1909 peer->group = NULL;
1910 if (group->conf->as)
1911 {
1912 peer_delete (peer);
1913 return 0;
1914 }
1915 peer_global_config_reset (peer);
1916 }
1917
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001918 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001919 {
1920 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1923 }
paul718e3742002-12-13 20:15:29 +00001924 else
1925 BGP_EVENT_ADD (peer, BGP_Stop);
1926
1927 return 0;
1928}
1929
1930/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001931static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001932bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001933{
1934 struct bgp *bgp;
1935 afi_t afi;
1936 safi_t safi;
1937
paul200df112005-06-01 11:17:05 +00001938 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1939 return NULL;
1940
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001941 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001942 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001943 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001944
1945 bgp->peer = list_new ();
1946 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1947
1948 bgp->group = list_new ();
1949 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1950
paulfee0f4c2004-09-13 05:12:46 +00001951 bgp->rsclient = list_new ();
1952 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1953
paul718e3742002-12-13 20:15:29 +00001954 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1955 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1956 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001957 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1958 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1959 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001960 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1961 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001962 }
1963
1964 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1965 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1966 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001967 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1968 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001969
1970 bgp->as = *as;
1971
1972 if (name)
1973 bgp->name = strdup (name);
1974
1975 return bgp;
1976}
1977
1978/* Return first entry of BGP. */
1979struct bgp *
paul94f2b392005-06-28 12:44:16 +00001980bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001981{
1982 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001983 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001984 return NULL;
1985}
1986
1987/* Lookup BGP entry. */
1988struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001989bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001990{
1991 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001992 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001993
paul1eb8ef22005-04-07 07:30:20 +00001994 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001995 if (bgp->as == as
1996 && ((bgp->name == NULL && name == NULL)
1997 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1998 return bgp;
1999 return NULL;
2000}
2001
2002/* Lookup BGP structure by view name. */
2003struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002004bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002005{
2006 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002008
paul1eb8ef22005-04-07 07:30:20 +00002009 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002010 if ((bgp->name == NULL && name == NULL)
2011 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2012 return bgp;
2013 return NULL;
2014}
2015
2016/* Called from VTY commands. */
2017int
paulfd79ac92004-10-13 05:06:08 +00002018bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002019{
2020 struct bgp *bgp;
2021
2022 /* Multiple instance check. */
2023 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2024 {
2025 if (name)
2026 bgp = bgp_lookup_by_name (name);
2027 else
2028 bgp = bgp_get_default ();
2029
2030 /* Already exists. */
2031 if (bgp)
2032 {
2033 if (bgp->as != *as)
2034 {
2035 *as = bgp->as;
2036 return BGP_ERR_INSTANCE_MISMATCH;
2037 }
2038 *bgp_val = bgp;
2039 return 0;
2040 }
2041 }
2042 else
2043 {
2044 /* BGP instance name can not be specified for single instance. */
2045 if (name)
2046 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2047
2048 /* Get default BGP structure if exists. */
2049 bgp = bgp_get_default ();
2050
2051 if (bgp)
2052 {
2053 if (bgp->as != *as)
2054 {
2055 *as = bgp->as;
2056 return BGP_ERR_AS_MISMATCH;
2057 }
2058 *bgp_val = bgp;
2059 return 0;
2060 }
2061 }
2062
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002063 bgp = bgp_create (as, name);
2064 bgp_router_id_set(bgp, &router_id_zebra);
2065 *bgp_val = bgp;
2066
Paul Jakmaad12dde2012-06-13 22:50:07 +01002067 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002068 if (list_isempty(bm->bgp)
2069 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002070 {
2071 if (bgp_socket (bm->port, bm->address) < 0)
2072 return BGP_ERR_INVALID_VALUE;
2073 }
2074
paul718e3742002-12-13 20:15:29 +00002075 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002076
2077 return 0;
2078}
2079
2080/* Delete BGP instance. */
2081int
2082bgp_delete (struct bgp *bgp)
2083{
2084 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002087 struct listnode *next;
2088 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002089 int i;
2090
2091 /* Delete static route. */
2092 bgp_static_delete (bgp);
2093
2094 /* Unset redistribution. */
2095 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2096 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2097 if (i != ZEBRA_ROUTE_BGP)
2098 bgp_redistribute_unset (bgp, afi, i);
2099
paul1eb8ef22005-04-07 07:30:20 +00002100 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002101 {
2102 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2103 {
2104 /* Send notify to remote peer. */
2105 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2106 }
2107
2108 peer_delete (peer);
2109 }
paul718e3742002-12-13 20:15:29 +00002110
Chris Caputo228da422009-07-18 05:44:03 +00002111 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002112 {
2113 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2114 {
2115 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2116 {
2117 /* Send notify to remote peer. */
2118 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2119 }
2120 }
2121 peer_group_delete (group);
2122 }
Chris Caputo228da422009-07-18 05:44:03 +00002123
2124 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002125
2126 if (bgp->peer_self) {
2127 peer_delete(bgp->peer_self);
2128 bgp->peer_self = NULL;
2129 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002130
2131 /* Remove visibility via the master list - there may however still be
2132 * routes to be processed still referencing the struct bgp.
2133 */
2134 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002135 if (list_isempty(bm->bgp))
2136 bgp_close ();
2137
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002138 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002139
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002140 return 0;
2141}
2142
2143static void bgp_free (struct bgp *);
2144
2145void
2146bgp_lock (struct bgp *bgp)
2147{
2148 ++bgp->lock;
2149}
2150
2151void
2152bgp_unlock(struct bgp *bgp)
2153{
Chris Caputo228da422009-07-18 05:44:03 +00002154 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002155 if (--bgp->lock == 0)
2156 bgp_free (bgp);
2157}
2158
2159static void
2160bgp_free (struct bgp *bgp)
2161{
2162 afi_t afi;
2163 safi_t safi;
2164
2165 list_delete (bgp->group);
2166 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002167 list_delete (bgp->rsclient);
2168
paul718e3742002-12-13 20:15:29 +00002169 if (bgp->name)
2170 free (bgp->name);
2171
2172 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2173 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2174 {
2175 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002176 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002177 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002178 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002179 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002180 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002181 }
2182 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002183}
2184
2185struct peer *
2186peer_lookup (struct bgp *bgp, union sockunion *su)
2187{
2188 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002189 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002190
Steve Hillfc4dc592009-07-28 17:54:35 +01002191 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002192 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002193 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2194 if (sockunion_same (&peer->su, su)
2195 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2196 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002197 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002198 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002199 {
2200 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002201
Paul Jakma2158ad22009-07-28 18:10:55 +01002202 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2204 if (sockunion_same (&peer->su, su)
2205 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2206 return peer;
paul718e3742002-12-13 20:15:29 +00002207 }
2208 return NULL;
2209}
2210
2211struct peer *
2212peer_lookup_with_open (union sockunion *su, as_t remote_as,
2213 struct in_addr *remote_id, int *as)
2214{
2215 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002216 struct listnode *node;
2217 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002218 struct bgp *bgp;
2219
Steve Hillfc4dc592009-07-28 17:54:35 +01002220 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002221 return NULL;
2222
Paul Jakma9d878772009-08-05 16:25:16 +01002223 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002224 {
Paul Jakma9d878772009-08-05 16:25:16 +01002225 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2226 {
2227 if (sockunion_same (&peer->su, su)
2228 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2229 {
2230 if (peer->as == remote_as
2231 && peer->remote_id.s_addr == remote_id->s_addr)
2232 return peer;
2233 if (peer->as == remote_as)
2234 *as = 1;
2235 }
2236 }
2237
2238 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2239 {
2240 if (sockunion_same (&peer->su, su)
2241 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2242 {
2243 if (peer->as == remote_as
2244 && peer->remote_id.s_addr == 0)
2245 return peer;
2246 if (peer->as == remote_as)
2247 *as = 1;
2248 }
2249 }
paul718e3742002-12-13 20:15:29 +00002250 }
2251 return NULL;
2252}
2253
2254/* If peer is configured at least one address family return 1. */
2255int
2256peer_active (struct peer *peer)
2257{
2258 if (peer->afc[AFI_IP][SAFI_UNICAST]
2259 || peer->afc[AFI_IP][SAFI_MULTICAST]
2260 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2261 || peer->afc[AFI_IP6][SAFI_UNICAST]
2262 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2263 return 1;
2264 return 0;
2265}
2266
2267/* If peer is negotiated at least one address family return 1. */
2268int
2269peer_active_nego (struct peer *peer)
2270{
2271 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2272 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2273 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2274 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2275 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2276 return 1;
2277 return 0;
2278}
2279
2280/* peer_flag_change_type. */
2281enum peer_change_type
2282{
2283 peer_change_none,
2284 peer_change_reset,
2285 peer_change_reset_in,
2286 peer_change_reset_out,
2287};
2288
paul94f2b392005-06-28 12:44:16 +00002289static void
paul718e3742002-12-13 20:15:29 +00002290peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2291 enum peer_change_type type)
2292{
2293 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2294 return;
2295
2296 if (type == peer_change_reset)
2297 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2298 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2299 else if (type == peer_change_reset_in)
2300 {
2301 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2302 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2303 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2304 else
2305 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2306 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2307 }
2308 else if (type == peer_change_reset_out)
2309 bgp_announce_route (peer, afi, safi);
2310}
2311
2312struct peer_flag_action
2313{
2314 /* Peer's flag. */
2315 u_int32_t flag;
2316
2317 /* This flag can be set for peer-group member. */
2318 u_char not_for_member;
2319
2320 /* Action when the flag is changed. */
2321 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002322
2323 /* Peer down cause */
2324 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002325};
2326
Stephen Hemminger03621952009-07-21 16:27:20 -07002327static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002328 {
2329 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2330 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2331 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2332 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2333 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002334 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002335 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002336 { 0, 0, 0 }
2337 };
2338
Stephen Hemminger03621952009-07-21 16:27:20 -07002339static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002340 {
2341 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2342 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2343 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2344 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2345 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2346 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2347 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2348 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2349 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2350 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2351 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2352 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2353 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002354 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002355 { 0, 0, 0 }
2356 };
2357
2358/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002359static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002360peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002361 struct peer_flag_action *action, u_int32_t flag)
2362{
2363 int i;
2364 int found = 0;
2365 int reset_in = 0;
2366 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002367 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002368
2369 /* Check peer's frag action. */
2370 for (i = 0; i < size; i++)
2371 {
2372 match = &action_list[i];
2373
2374 if (match->flag == 0)
2375 break;
2376
2377 if (match->flag & flag)
2378 {
2379 found = 1;
2380
2381 if (match->type == peer_change_reset_in)
2382 reset_in = 1;
2383 if (match->type == peer_change_reset_out)
2384 reset_out = 1;
2385 if (match->type == peer_change_reset)
2386 {
2387 reset_in = 1;
2388 reset_out = 1;
2389 }
2390 if (match->not_for_member)
2391 action->not_for_member = 1;
2392 }
2393 }
2394
2395 /* Set peer clear type. */
2396 if (reset_in && reset_out)
2397 action->type = peer_change_reset;
2398 else if (reset_in)
2399 action->type = peer_change_reset_in;
2400 else if (reset_out)
2401 action->type = peer_change_reset_out;
2402 else
2403 action->type = peer_change_none;
2404
2405 return found;
2406}
2407
paul94f2b392005-06-28 12:44:16 +00002408static void
paul718e3742002-12-13 20:15:29 +00002409peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2410{
2411 if (flag == PEER_FLAG_SHUTDOWN)
2412 {
2413 if (CHECK_FLAG (peer->flags, flag))
2414 {
hasso93406d82005-02-02 14:40:33 +00002415 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2416 peer_nsf_stop (peer);
2417
hasso0a486e52005-02-01 20:57:17 +00002418 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2419 if (peer->t_pmax_restart)
2420 {
2421 BGP_TIMER_OFF (peer->t_pmax_restart);
2422 if (BGP_DEBUG (events, EVENTS))
2423 zlog_debug ("%s Maximum-prefix restart timer canceled",
2424 peer->host);
2425 }
2426
hasso93406d82005-02-02 14:40:33 +00002427 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2428 peer_nsf_stop (peer);
2429
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002430 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002431 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2432 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2433 else
2434 BGP_EVENT_ADD (peer, BGP_Stop);
2435 }
2436 else
2437 {
2438 peer->v_start = BGP_INIT_START_TIMER;
2439 BGP_EVENT_ADD (peer, BGP_Stop);
2440 }
2441 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002442 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002443 {
hassoc9502432005-02-01 22:01:48 +00002444 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2445 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2446 else if (flag == PEER_FLAG_PASSIVE)
2447 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002448 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002449 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002450
hassoc9502432005-02-01 22:01:48 +00002451 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2452 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002453 }
2454 else
2455 BGP_EVENT_ADD (peer, BGP_Stop);
2456}
2457
2458/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002459static int
paul718e3742002-12-13 20:15:29 +00002460peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2461{
2462 int found;
2463 int size;
2464 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002465 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002466 struct peer_flag_action action;
2467
2468 memset (&action, 0, sizeof (struct peer_flag_action));
2469 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2470
2471 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2472
2473 /* No flag action is found. */
2474 if (! found)
2475 return BGP_ERR_INVALID_FLAG;
2476
2477 /* Not for peer-group member. */
2478 if (action.not_for_member && peer_group_active (peer))
2479 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2480
2481 /* When unset the peer-group member's flag we have to check
2482 peer-group configuration. */
2483 if (! set && peer_group_active (peer))
2484 if (CHECK_FLAG (peer->group->conf->flags, flag))
2485 {
2486 if (flag == PEER_FLAG_SHUTDOWN)
2487 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2488 else
2489 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2490 }
2491
2492 /* Flag conflict check. */
2493 if (set
2494 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2495 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2496 return BGP_ERR_PEER_FLAG_CONFLICT;
2497
2498 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2499 {
2500 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2501 return 0;
2502 if (! set && ! CHECK_FLAG (peer->flags, flag))
2503 return 0;
2504 }
2505
2506 if (set)
2507 SET_FLAG (peer->flags, flag);
2508 else
2509 UNSET_FLAG (peer->flags, flag);
2510
2511 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2512 {
2513 if (action.type == peer_change_reset)
2514 peer_flag_modify_action (peer, flag);
2515
2516 return 0;
2517 }
2518
2519 /* peer-group member updates. */
2520 group = peer->group;
2521
paul1eb8ef22005-04-07 07:30:20 +00002522 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002523 {
2524 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2525 continue;
2526
2527 if (! set && ! CHECK_FLAG (peer->flags, flag))
2528 continue;
2529
2530 if (set)
2531 SET_FLAG (peer->flags, flag);
2532 else
2533 UNSET_FLAG (peer->flags, flag);
2534
2535 if (action.type == peer_change_reset)
2536 peer_flag_modify_action (peer, flag);
2537 }
2538 return 0;
2539}
2540
2541int
2542peer_flag_set (struct peer *peer, u_int32_t flag)
2543{
2544 return peer_flag_modify (peer, flag, 1);
2545}
2546
2547int
2548peer_flag_unset (struct peer *peer, u_int32_t flag)
2549{
2550 return peer_flag_modify (peer, flag, 0);
2551}
2552
paul94f2b392005-06-28 12:44:16 +00002553static int
paul718e3742002-12-13 20:15:29 +00002554peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2555{
2556 if (peer->af_group[afi][safi])
2557 return 1;
2558 return 0;
2559}
2560
paul94f2b392005-06-28 12:44:16 +00002561static int
paul718e3742002-12-13 20:15:29 +00002562peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2563 int set)
2564{
2565 int found;
2566 int size;
paul1eb8ef22005-04-07 07:30:20 +00002567 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002568 struct peer_group *group;
2569 struct peer_flag_action action;
2570
2571 memset (&action, 0, sizeof (struct peer_flag_action));
2572 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2573
2574 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2575
2576 /* No flag action is found. */
2577 if (! found)
2578 return BGP_ERR_INVALID_FLAG;
2579
2580 /* Adress family must be activated. */
2581 if (! peer->afc[afi][safi])
2582 return BGP_ERR_PEER_INACTIVE;
2583
2584 /* Not for peer-group member. */
2585 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2586 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2587
2588 /* Spcecial check for reflector client. */
2589 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2590 && peer_sort (peer) != BGP_PEER_IBGP)
2591 return BGP_ERR_NOT_INTERNAL_PEER;
2592
2593 /* Spcecial check for remove-private-AS. */
2594 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2595 && peer_sort (peer) == BGP_PEER_IBGP)
2596 return BGP_ERR_REMOVE_PRIVATE_AS;
2597
2598 /* When unset the peer-group member's flag we have to check
2599 peer-group configuration. */
2600 if (! set && peer->af_group[afi][safi])
2601 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2602 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2603
2604 /* When current flag configuration is same as requested one. */
2605 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2606 {
2607 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2608 return 0;
2609 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2610 return 0;
2611 }
2612
2613 if (set)
2614 SET_FLAG (peer->af_flags[afi][safi], flag);
2615 else
2616 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2617
2618 /* Execute action when peer is established. */
2619 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2620 && peer->status == Established)
2621 {
2622 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2623 bgp_clear_adj_in (peer, afi, safi);
2624 else
hassoe0701b72004-05-20 09:19:34 +00002625 {
2626 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2627 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2628 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2629 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2630 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2631 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2632 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2633 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2634
2635 peer_change_action (peer, afi, safi, action.type);
2636 }
2637
paul718e3742002-12-13 20:15:29 +00002638 }
2639
2640 /* Peer group member updates. */
2641 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2642 {
2643 group = peer->group;
2644
paul1eb8ef22005-04-07 07:30:20 +00002645 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002646 {
2647 if (! peer->af_group[afi][safi])
2648 continue;
2649
2650 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2651 continue;
2652
2653 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2654 continue;
2655
2656 if (set)
2657 SET_FLAG (peer->af_flags[afi][safi], flag);
2658 else
2659 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2660
2661 if (peer->status == Established)
2662 {
2663 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2664 bgp_clear_adj_in (peer, afi, safi);
2665 else
hassoe0701b72004-05-20 09:19:34 +00002666 {
2667 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2668 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2669 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2670 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2671 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2672 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2673 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2674 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2675
2676 peer_change_action (peer, afi, safi, action.type);
2677 }
paul718e3742002-12-13 20:15:29 +00002678 }
2679 }
2680 }
2681 return 0;
2682}
2683
2684int
2685peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2686{
2687 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2688}
2689
2690int
2691peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2692{
2693 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2694}
2695
2696/* EBGP multihop configuration. */
2697int
2698peer_ebgp_multihop_set (struct peer *peer, int ttl)
2699{
2700 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002701 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002702 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002703
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002704 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002705 return 0;
2706
Nick Hilliardfa411a22011-03-23 15:33:17 +00002707 /* see comment in peer_ttl_security_hops_set() */
2708 if (ttl != MAXTTL)
2709 {
2710 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2711 {
2712 group = peer->group;
2713 if (group->conf->gtsm_hops != 0)
2714 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2715
2716 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2717 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002718 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002719 continue;
2720
2721 if (peer1->gtsm_hops != 0)
2722 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2723 }
2724 }
2725 else
2726 {
2727 if (peer->gtsm_hops != 0)
2728 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2729 }
2730 }
2731
paul718e3742002-12-13 20:15:29 +00002732 peer->ttl = ttl;
2733
2734 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2735 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002736 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002737 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002738 }
2739 else
2740 {
2741 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002742 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002743 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002744 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002745 continue;
paul718e3742002-12-13 20:15:29 +00002746
pauleb821182004-05-01 08:44:08 +00002747 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002748
pauleb821182004-05-01 08:44:08 +00002749 if (peer->fd >= 0)
2750 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2751 }
paul718e3742002-12-13 20:15:29 +00002752 }
2753 return 0;
2754}
2755
2756int
2757peer_ebgp_multihop_unset (struct peer *peer)
2758{
2759 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002760 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002761
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002762 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002763 return 0;
2764
Nick Hilliardfa411a22011-03-23 15:33:17 +00002765 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2766 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2767
paul718e3742002-12-13 20:15:29 +00002768 if (peer_group_active (peer))
2769 peer->ttl = peer->group->conf->ttl;
2770 else
2771 peer->ttl = 1;
2772
2773 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2774 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002775 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002776 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002777 }
2778 else
2779 {
2780 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002781 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002782 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002783 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002784 continue;
paul718e3742002-12-13 20:15:29 +00002785
pauleb821182004-05-01 08:44:08 +00002786 peer->ttl = 1;
2787
2788 if (peer->fd >= 0)
2789 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2790 }
paul718e3742002-12-13 20:15:29 +00002791 }
2792 return 0;
2793}
2794
2795/* Neighbor description. */
2796int
2797peer_description_set (struct peer *peer, char *desc)
2798{
2799 if (peer->desc)
2800 XFREE (MTYPE_PEER_DESC, peer->desc);
2801
2802 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2803
2804 return 0;
2805}
2806
2807int
2808peer_description_unset (struct peer *peer)
2809{
2810 if (peer->desc)
2811 XFREE (MTYPE_PEER_DESC, peer->desc);
2812
2813 peer->desc = NULL;
2814
2815 return 0;
2816}
2817
2818/* Neighbor update-source. */
2819int
paulfd79ac92004-10-13 05:06:08 +00002820peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002821{
2822 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002823 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002824
2825 if (peer->update_if)
2826 {
2827 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2828 && strcmp (peer->update_if, ifname) == 0)
2829 return 0;
2830
2831 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2832 peer->update_if = NULL;
2833 }
2834
2835 if (peer->update_source)
2836 {
2837 sockunion_free (peer->update_source);
2838 peer->update_source = NULL;
2839 }
2840
2841 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2842
2843 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2844 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002845 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002846 {
2847 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2848 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2849 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2850 }
paul718e3742002-12-13 20:15:29 +00002851 else
2852 BGP_EVENT_ADD (peer, BGP_Stop);
2853 return 0;
2854 }
2855
2856 /* peer-group member updates. */
2857 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002858 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002859 {
2860 if (peer->update_if)
2861 {
2862 if (strcmp (peer->update_if, ifname) == 0)
2863 continue;
2864
2865 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2866 peer->update_if = NULL;
2867 }
2868
2869 if (peer->update_source)
2870 {
2871 sockunion_free (peer->update_source);
2872 peer->update_source = NULL;
2873 }
2874
2875 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2876
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002877 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002878 {
2879 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2880 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2881 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2882 }
paul718e3742002-12-13 20:15:29 +00002883 else
2884 BGP_EVENT_ADD (peer, BGP_Stop);
2885 }
2886 return 0;
2887}
2888
2889int
2890peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2891{
2892 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002893 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002894
2895 if (peer->update_source)
2896 {
2897 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2898 && sockunion_cmp (peer->update_source, su) == 0)
2899 return 0;
2900 sockunion_free (peer->update_source);
2901 peer->update_source = NULL;
2902 }
2903
2904 if (peer->update_if)
2905 {
2906 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2907 peer->update_if = NULL;
2908 }
2909
2910 peer->update_source = sockunion_dup (su);
2911
2912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2913 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002914 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002915 {
2916 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2917 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2918 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2919 }
paul718e3742002-12-13 20:15:29 +00002920 else
2921 BGP_EVENT_ADD (peer, BGP_Stop);
2922 return 0;
2923 }
2924
2925 /* peer-group member updates. */
2926 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002927 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002928 {
2929 if (peer->update_source)
2930 {
2931 if (sockunion_cmp (peer->update_source, su) == 0)
2932 continue;
2933 sockunion_free (peer->update_source);
2934 peer->update_source = NULL;
2935 }
2936
2937 if (peer->update_if)
2938 {
2939 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2940 peer->update_if = NULL;
2941 }
2942
2943 peer->update_source = sockunion_dup (su);
2944
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002945 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002946 {
2947 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2948 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2949 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2950 }
paul718e3742002-12-13 20:15:29 +00002951 else
2952 BGP_EVENT_ADD (peer, BGP_Stop);
2953 }
2954 return 0;
2955}
2956
2957int
2958peer_update_source_unset (struct peer *peer)
2959{
2960 union sockunion *su;
2961 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002962 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002963
2964 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2965 && ! peer->update_source
2966 && ! peer->update_if)
2967 return 0;
2968
2969 if (peer->update_source)
2970 {
2971 sockunion_free (peer->update_source);
2972 peer->update_source = NULL;
2973 }
2974 if (peer->update_if)
2975 {
2976 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2977 peer->update_if = NULL;
2978 }
2979
2980 if (peer_group_active (peer))
2981 {
2982 group = peer->group;
2983
2984 if (group->conf->update_source)
2985 {
2986 su = sockunion_dup (group->conf->update_source);
2987 peer->update_source = su;
2988 }
2989 else if (group->conf->update_if)
2990 peer->update_if =
2991 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2992 }
2993
2994 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2995 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002996 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002997 {
2998 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2999 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3000 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3001 }
paul718e3742002-12-13 20:15:29 +00003002 else
3003 BGP_EVENT_ADD (peer, BGP_Stop);
3004 return 0;
3005 }
3006
3007 /* peer-group member updates. */
3008 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003009 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003010 {
3011 if (! peer->update_source && ! peer->update_if)
3012 continue;
3013
3014 if (peer->update_source)
3015 {
3016 sockunion_free (peer->update_source);
3017 peer->update_source = NULL;
3018 }
3019
3020 if (peer->update_if)
3021 {
3022 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3023 peer->update_if = NULL;
3024 }
3025
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003026 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003027 {
3028 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3029 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3030 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3031 }
paul718e3742002-12-13 20:15:29 +00003032 else
3033 BGP_EVENT_ADD (peer, BGP_Stop);
3034 }
3035 return 0;
3036}
3037
3038int
3039peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003040 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003041{
3042 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003043 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003044
3045 /* Adress family must be activated. */
3046 if (! peer->afc[afi][safi])
3047 return BGP_ERR_PEER_INACTIVE;
3048
3049 /* Default originate can't be used for peer group memeber. */
3050 if (peer_is_group_member (peer, afi, safi))
3051 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3052
3053 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3054 || (rmap && ! peer->default_rmap[afi][safi].name)
3055 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3056 {
3057 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3058
3059 if (rmap)
3060 {
3061 if (peer->default_rmap[afi][safi].name)
3062 free (peer->default_rmap[afi][safi].name);
3063 peer->default_rmap[afi][safi].name = strdup (rmap);
3064 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3065 }
3066 }
3067
3068 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3069 {
3070 if (peer->status == Established && peer->afc_nego[afi][safi])
3071 bgp_default_originate (peer, afi, safi, 0);
3072 return 0;
3073 }
3074
3075 /* peer-group member updates. */
3076 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003077 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003078 {
3079 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3080
3081 if (rmap)
3082 {
3083 if (peer->default_rmap[afi][safi].name)
3084 free (peer->default_rmap[afi][safi].name);
3085 peer->default_rmap[afi][safi].name = strdup (rmap);
3086 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3087 }
3088
3089 if (peer->status == Established && peer->afc_nego[afi][safi])
3090 bgp_default_originate (peer, afi, safi, 0);
3091 }
3092 return 0;
3093}
3094
3095int
3096peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3097{
3098 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003099 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003100
3101 /* Adress family must be activated. */
3102 if (! peer->afc[afi][safi])
3103 return BGP_ERR_PEER_INACTIVE;
3104
3105 /* Default originate can't be used for peer group memeber. */
3106 if (peer_is_group_member (peer, afi, safi))
3107 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3108
3109 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3110 {
3111 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3112
3113 if (peer->default_rmap[afi][safi].name)
3114 free (peer->default_rmap[afi][safi].name);
3115 peer->default_rmap[afi][safi].name = NULL;
3116 peer->default_rmap[afi][safi].map = NULL;
3117 }
3118
3119 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3120 {
3121 if (peer->status == Established && peer->afc_nego[afi][safi])
3122 bgp_default_originate (peer, afi, safi, 1);
3123 return 0;
3124 }
3125
3126 /* peer-group member updates. */
3127 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003128 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003129 {
3130 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3131
3132 if (peer->default_rmap[afi][safi].name)
3133 free (peer->default_rmap[afi][safi].name);
3134 peer->default_rmap[afi][safi].name = NULL;
3135 peer->default_rmap[afi][safi].map = NULL;
3136
3137 if (peer->status == Established && peer->afc_nego[afi][safi])
3138 bgp_default_originate (peer, afi, safi, 1);
3139 }
3140 return 0;
3141}
3142
3143int
3144peer_port_set (struct peer *peer, u_int16_t port)
3145{
3146 peer->port = port;
3147 return 0;
3148}
3149
3150int
3151peer_port_unset (struct peer *peer)
3152{
3153 peer->port = BGP_PORT_DEFAULT;
3154 return 0;
3155}
3156
3157/* neighbor weight. */
3158int
3159peer_weight_set (struct peer *peer, u_int16_t weight)
3160{
3161 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003163
3164 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3165 peer->weight = weight;
3166
3167 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3168 return 0;
3169
3170 /* peer-group member updates. */
3171 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003172 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003173 {
3174 peer->weight = group->conf->weight;
3175 }
3176 return 0;
3177}
3178
3179int
3180peer_weight_unset (struct peer *peer)
3181{
3182 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003183 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003184
3185 /* Set default weight. */
3186 if (peer_group_active (peer))
3187 peer->weight = peer->group->conf->weight;
3188 else
3189 peer->weight = 0;
3190
3191 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3192
3193 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3194 return 0;
3195
3196 /* peer-group member updates. */
3197 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003198 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003199 {
3200 peer->weight = 0;
3201 }
3202 return 0;
3203}
3204
3205int
3206peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3207{
3208 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003209 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003210
3211 /* Not for peer group memeber. */
3212 if (peer_group_active (peer))
3213 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3214
3215 /* keepalive value check. */
3216 if (keepalive > 65535)
3217 return BGP_ERR_INVALID_VALUE;
3218
3219 /* Holdtime value check. */
3220 if (holdtime > 65535)
3221 return BGP_ERR_INVALID_VALUE;
3222
3223 /* Holdtime value must be either 0 or greater than 3. */
3224 if (holdtime < 3 && holdtime != 0)
3225 return BGP_ERR_INVALID_VALUE;
3226
3227 /* Set value to the configuration. */
3228 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3229 peer->holdtime = holdtime;
3230 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3231
3232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3233 return 0;
3234
3235 /* peer-group member updates. */
3236 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003237 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003238 {
3239 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3240 peer->holdtime = group->conf->holdtime;
3241 peer->keepalive = group->conf->keepalive;
3242 }
3243 return 0;
3244}
3245
3246int
3247peer_timers_unset (struct peer *peer)
3248{
3249 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003250 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003251
3252 if (peer_group_active (peer))
3253 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3254
3255 /* Clear configuration. */
3256 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3257 peer->keepalive = 0;
3258 peer->holdtime = 0;
3259
3260 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3261 return 0;
3262
3263 /* peer-group member updates. */
3264 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003265 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003266 {
3267 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3268 peer->holdtime = 0;
3269 peer->keepalive = 0;
3270 }
3271
3272 return 0;
3273}
3274
3275int
3276peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3277{
3278 if (peer_group_active (peer))
3279 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3280
3281 if (connect > 65535)
3282 return BGP_ERR_INVALID_VALUE;
3283
3284 /* Set value to the configuration. */
3285 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3286 peer->connect = connect;
3287
3288 /* Set value to timer setting. */
3289 peer->v_connect = connect;
3290
3291 return 0;
3292}
3293
3294int
3295peer_timers_connect_unset (struct peer *peer)
3296{
3297 if (peer_group_active (peer))
3298 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3299
3300 /* Clear configuration. */
3301 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3302 peer->connect = 0;
3303
3304 /* Set timer setting to default value. */
3305 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3306
3307 return 0;
3308}
3309
3310int
3311peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3312{
3313 if (peer_group_active (peer))
3314 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3315
3316 if (routeadv > 600)
3317 return BGP_ERR_INVALID_VALUE;
3318
3319 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3320 peer->routeadv = routeadv;
3321 peer->v_routeadv = routeadv;
3322
3323 return 0;
3324}
3325
3326int
3327peer_advertise_interval_unset (struct peer *peer)
3328{
3329 if (peer_group_active (peer))
3330 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3331
3332 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3333 peer->routeadv = 0;
3334
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003335 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003336 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3337 else
3338 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3339
3340 return 0;
3341}
3342
paul718e3742002-12-13 20:15:29 +00003343/* neighbor interface */
3344int
paulfd79ac92004-10-13 05:06:08 +00003345peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003346{
3347 if (peer->ifname)
3348 free (peer->ifname);
3349 peer->ifname = strdup (str);
3350
3351 return 0;
3352}
3353
3354int
3355peer_interface_unset (struct peer *peer)
3356{
3357 if (peer->ifname)
3358 free (peer->ifname);
3359 peer->ifname = NULL;
3360
3361 return 0;
3362}
3363
3364/* Allow-as in. */
3365int
3366peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3367{
3368 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003369 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003370
3371 if (allow_num < 1 || allow_num > 10)
3372 return BGP_ERR_INVALID_VALUE;
3373
3374 if (peer->allowas_in[afi][safi] != allow_num)
3375 {
3376 peer->allowas_in[afi][safi] = allow_num;
3377 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3378 peer_change_action (peer, afi, safi, peer_change_reset_in);
3379 }
3380
3381 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3382 return 0;
3383
3384 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003385 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003386 {
3387 if (peer->allowas_in[afi][safi] != allow_num)
3388 {
3389 peer->allowas_in[afi][safi] = allow_num;
3390 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3391 peer_change_action (peer, afi, safi, peer_change_reset_in);
3392 }
3393
3394 }
3395 return 0;
3396}
3397
3398int
3399peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3400{
3401 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003402 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003403
3404 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3405 {
3406 peer->allowas_in[afi][safi] = 0;
3407 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3408 }
3409
3410 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3411 return 0;
3412
3413 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003414 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003415 {
3416 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3417 {
3418 peer->allowas_in[afi][safi] = 0;
3419 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3420 }
3421 }
3422 return 0;
3423}
3424
3425int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003426peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003427{
3428 struct bgp *bgp = peer->bgp;
3429 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003430 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003431
3432 if (peer_sort (peer) != BGP_PEER_EBGP
3433 && peer_sort (peer) != BGP_PEER_INTERNAL)
3434 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3435
3436 if (bgp->as == as)
3437 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3438
3439 if (peer_group_active (peer))
3440 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3441
Andrew Certain9d3f9702012-11-07 23:50:07 +00003442 if (peer->as == as)
3443 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3444
paul718e3742002-12-13 20:15:29 +00003445 if (peer->change_local_as == as &&
3446 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003447 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3448 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3449 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003450 return 0;
3451
3452 peer->change_local_as = as;
3453 if (no_prepend)
3454 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3455 else
3456 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3457
Andrew Certain9d3f9702012-11-07 23:50:07 +00003458 if (replace_as)
3459 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3460 else
3461 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3462
paul718e3742002-12-13 20:15:29 +00003463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3464 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003465 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003466 {
3467 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3468 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3469 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3470 }
paul718e3742002-12-13 20:15:29 +00003471 else
3472 BGP_EVENT_ADD (peer, BGP_Stop);
3473
3474 return 0;
3475 }
3476
3477 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003478 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003479 {
3480 peer->change_local_as = as;
3481 if (no_prepend)
3482 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3483 else
3484 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3485
Andrew Certain9d3f9702012-11-07 23:50:07 +00003486 if (replace_as)
3487 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3488 else
3489 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3490
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003491 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003492 {
3493 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3494 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3495 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3496 }
paul718e3742002-12-13 20:15:29 +00003497 else
3498 BGP_EVENT_ADD (peer, BGP_Stop);
3499 }
3500
3501 return 0;
3502}
3503
3504int
3505peer_local_as_unset (struct peer *peer)
3506{
3507 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003508 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003509
3510 if (peer_group_active (peer))
3511 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3512
3513 if (! peer->change_local_as)
3514 return 0;
3515
3516 peer->change_local_as = 0;
3517 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003518 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003519
3520 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3521 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003522 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003523 {
3524 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3525 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3526 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3527 }
paul718e3742002-12-13 20:15:29 +00003528 else
3529 BGP_EVENT_ADD (peer, BGP_Stop);
3530
3531 return 0;
3532 }
3533
3534 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003535 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003536 {
3537 peer->change_local_as = 0;
3538 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003539 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003540
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003541 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003542 {
3543 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3544 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3545 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3546 }
paul718e3742002-12-13 20:15:29 +00003547 else
3548 BGP_EVENT_ADD (peer, BGP_Stop);
3549 }
3550 return 0;
3551}
3552
Paul Jakma0df7c912008-07-21 21:02:49 +00003553/* Set password for authenticating with the peer. */
3554int
3555peer_password_set (struct peer *peer, const char *password)
3556{
3557 struct listnode *nn, *nnode;
3558 int len = password ? strlen(password) : 0;
3559 int ret = BGP_SUCCESS;
3560
3561 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3562 return BGP_ERR_INVALID_VALUE;
3563
3564 if (peer->password && strcmp (peer->password, password) == 0
3565 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3566 return 0;
3567
3568 if (peer->password)
3569 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3570
3571 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3572
3573 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3574 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003575 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3576 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003577 else
3578 BGP_EVENT_ADD (peer, BGP_Stop);
3579
3580 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3581 }
3582
3583 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3584 {
3585 if (peer->password && strcmp (peer->password, password) == 0)
3586 continue;
3587
3588 if (peer->password)
3589 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3590
3591 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3592
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003593 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003594 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3595 else
3596 BGP_EVENT_ADD (peer, BGP_Stop);
3597
3598 if (bgp_md5_set (peer) < 0)
3599 ret = BGP_ERR_TCPSIG_FAILED;
3600 }
3601
3602 return ret;
3603}
3604
3605int
3606peer_password_unset (struct peer *peer)
3607{
3608 struct listnode *nn, *nnode;
3609
3610 if (!peer->password
3611 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3612 return 0;
3613
3614 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3615 {
3616 if (peer_group_active (peer)
3617 && peer->group->conf->password
3618 && strcmp (peer->group->conf->password, peer->password) == 0)
3619 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3620
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003621 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003622 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3623 else
3624 BGP_EVENT_ADD (peer, BGP_Stop);
3625
3626 if (peer->password)
3627 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3628
3629 peer->password = NULL;
3630
3631 bgp_md5_set (peer);
3632
3633 return 0;
3634 }
3635
3636 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3637 peer->password = NULL;
3638
3639 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3640 {
3641 if (!peer->password)
3642 continue;
3643
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003644 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003645 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3646 else
3647 BGP_EVENT_ADD (peer, BGP_Stop);
3648
3649 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3650 peer->password = NULL;
3651
3652 bgp_md5_set (peer);
3653 }
3654
3655 return 0;
3656}
3657
paul718e3742002-12-13 20:15:29 +00003658/* Set distribute list to the peer. */
3659int
3660peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003661 const char *name)
paul718e3742002-12-13 20:15:29 +00003662{
3663 struct bgp_filter *filter;
3664 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003665 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003666
3667 if (! peer->afc[afi][safi])
3668 return BGP_ERR_PEER_INACTIVE;
3669
3670 if (direct != FILTER_IN && direct != FILTER_OUT)
3671 return BGP_ERR_INVALID_VALUE;
3672
3673 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3674 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3675
3676 filter = &peer->filter[afi][safi];
3677
3678 if (filter->plist[direct].name)
3679 return BGP_ERR_PEER_FILTER_CONFLICT;
3680
3681 if (filter->dlist[direct].name)
3682 free (filter->dlist[direct].name);
3683 filter->dlist[direct].name = strdup (name);
3684 filter->dlist[direct].alist = access_list_lookup (afi, name);
3685
3686 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3687 return 0;
3688
3689 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003690 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003691 {
3692 filter = &peer->filter[afi][safi];
3693
3694 if (! peer->af_group[afi][safi])
3695 continue;
3696
3697 if (filter->dlist[direct].name)
3698 free (filter->dlist[direct].name);
3699 filter->dlist[direct].name = strdup (name);
3700 filter->dlist[direct].alist = access_list_lookup (afi, name);
3701 }
3702
3703 return 0;
3704}
3705
3706int
3707peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3708{
3709 struct bgp_filter *filter;
3710 struct bgp_filter *gfilter;
3711 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003712 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003713
3714 if (! peer->afc[afi][safi])
3715 return BGP_ERR_PEER_INACTIVE;
3716
3717 if (direct != FILTER_IN && direct != FILTER_OUT)
3718 return BGP_ERR_INVALID_VALUE;
3719
3720 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3721 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3722
3723 filter = &peer->filter[afi][safi];
3724
3725 /* apply peer-group filter */
3726 if (peer->af_group[afi][safi])
3727 {
3728 gfilter = &peer->group->conf->filter[afi][safi];
3729
3730 if (gfilter->dlist[direct].name)
3731 {
3732 if (filter->dlist[direct].name)
3733 free (filter->dlist[direct].name);
3734 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3735 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3736 return 0;
3737 }
3738 }
3739
3740 if (filter->dlist[direct].name)
3741 free (filter->dlist[direct].name);
3742 filter->dlist[direct].name = NULL;
3743 filter->dlist[direct].alist = NULL;
3744
3745 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3746 return 0;
3747
3748 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003749 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003750 {
3751 filter = &peer->filter[afi][safi];
3752
3753 if (! peer->af_group[afi][safi])
3754 continue;
3755
3756 if (filter->dlist[direct].name)
3757 free (filter->dlist[direct].name);
3758 filter->dlist[direct].name = NULL;
3759 filter->dlist[direct].alist = NULL;
3760 }
3761
3762 return 0;
3763}
3764
3765/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003766static void
paul718e3742002-12-13 20:15:29 +00003767peer_distribute_update (struct access_list *access)
3768{
3769 afi_t afi;
3770 safi_t safi;
3771 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003772 struct listnode *mnode, *mnnode;
3773 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003774 struct bgp *bgp;
3775 struct peer *peer;
3776 struct peer_group *group;
3777 struct bgp_filter *filter;
3778
paul1eb8ef22005-04-07 07:30:20 +00003779 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003780 {
paul1eb8ef22005-04-07 07:30:20 +00003781 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003782 {
3783 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3784 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3785 {
3786 filter = &peer->filter[afi][safi];
3787
3788 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3789 {
3790 if (filter->dlist[direct].name)
3791 filter->dlist[direct].alist =
3792 access_list_lookup (afi, filter->dlist[direct].name);
3793 else
3794 filter->dlist[direct].alist = NULL;
3795 }
3796 }
3797 }
paul1eb8ef22005-04-07 07:30:20 +00003798 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003799 {
3800 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3801 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3802 {
3803 filter = &group->conf->filter[afi][safi];
3804
3805 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3806 {
3807 if (filter->dlist[direct].name)
3808 filter->dlist[direct].alist =
3809 access_list_lookup (afi, filter->dlist[direct].name);
3810 else
3811 filter->dlist[direct].alist = NULL;
3812 }
3813 }
3814 }
3815 }
3816}
3817
3818/* Set prefix list to the peer. */
3819int
3820peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003821 const char *name)
paul718e3742002-12-13 20:15:29 +00003822{
3823 struct bgp_filter *filter;
3824 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003825 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003826
3827 if (! peer->afc[afi][safi])
3828 return BGP_ERR_PEER_INACTIVE;
3829
3830 if (direct != FILTER_IN && direct != FILTER_OUT)
3831 return BGP_ERR_INVALID_VALUE;
3832
3833 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3834 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3835
3836 filter = &peer->filter[afi][safi];
3837
3838 if (filter->dlist[direct].name)
3839 return BGP_ERR_PEER_FILTER_CONFLICT;
3840
3841 if (filter->plist[direct].name)
3842 free (filter->plist[direct].name);
3843 filter->plist[direct].name = strdup (name);
3844 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3845
3846 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3847 return 0;
3848
3849 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003850 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003851 {
3852 filter = &peer->filter[afi][safi];
3853
3854 if (! peer->af_group[afi][safi])
3855 continue;
3856
3857 if (filter->plist[direct].name)
3858 free (filter->plist[direct].name);
3859 filter->plist[direct].name = strdup (name);
3860 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3861 }
3862 return 0;
3863}
3864
3865int
3866peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3867{
3868 struct bgp_filter *filter;
3869 struct bgp_filter *gfilter;
3870 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003871 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003872
3873 if (! peer->afc[afi][safi])
3874 return BGP_ERR_PEER_INACTIVE;
3875
3876 if (direct != FILTER_IN && direct != FILTER_OUT)
3877 return BGP_ERR_INVALID_VALUE;
3878
3879 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3880 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3881
3882 filter = &peer->filter[afi][safi];
3883
3884 /* apply peer-group filter */
3885 if (peer->af_group[afi][safi])
3886 {
3887 gfilter = &peer->group->conf->filter[afi][safi];
3888
3889 if (gfilter->plist[direct].name)
3890 {
3891 if (filter->plist[direct].name)
3892 free (filter->plist[direct].name);
3893 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3894 filter->plist[direct].plist = gfilter->plist[direct].plist;
3895 return 0;
3896 }
3897 }
3898
3899 if (filter->plist[direct].name)
3900 free (filter->plist[direct].name);
3901 filter->plist[direct].name = NULL;
3902 filter->plist[direct].plist = NULL;
3903
3904 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3905 return 0;
3906
3907 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003908 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003909 {
3910 filter = &peer->filter[afi][safi];
3911
3912 if (! peer->af_group[afi][safi])
3913 continue;
3914
3915 if (filter->plist[direct].name)
3916 free (filter->plist[direct].name);
3917 filter->plist[direct].name = NULL;
3918 filter->plist[direct].plist = NULL;
3919 }
3920
3921 return 0;
3922}
3923
3924/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003925static void
paul718e3742002-12-13 20:15:29 +00003926peer_prefix_list_update (struct prefix_list *plist)
3927{
paul1eb8ef22005-04-07 07:30:20 +00003928 struct listnode *mnode, *mnnode;
3929 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003930 struct bgp *bgp;
3931 struct peer *peer;
3932 struct peer_group *group;
3933 struct bgp_filter *filter;
3934 afi_t afi;
3935 safi_t safi;
3936 int direct;
3937
paul1eb8ef22005-04-07 07:30:20 +00003938 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003939 {
paul1eb8ef22005-04-07 07:30:20 +00003940 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003941 {
3942 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3943 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3944 {
3945 filter = &peer->filter[afi][safi];
3946
3947 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3948 {
3949 if (filter->plist[direct].name)
3950 filter->plist[direct].plist =
3951 prefix_list_lookup (afi, filter->plist[direct].name);
3952 else
3953 filter->plist[direct].plist = NULL;
3954 }
3955 }
3956 }
paul1eb8ef22005-04-07 07:30:20 +00003957 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003958 {
3959 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3960 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3961 {
3962 filter = &group->conf->filter[afi][safi];
3963
3964 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3965 {
3966 if (filter->plist[direct].name)
3967 filter->plist[direct].plist =
3968 prefix_list_lookup (afi, filter->plist[direct].name);
3969 else
3970 filter->plist[direct].plist = NULL;
3971 }
3972 }
3973 }
3974 }
3975}
3976
3977int
3978peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003979 const char *name)
paul718e3742002-12-13 20:15:29 +00003980{
3981 struct bgp_filter *filter;
3982 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003984
3985 if (! peer->afc[afi][safi])
3986 return BGP_ERR_PEER_INACTIVE;
3987
3988 if (direct != FILTER_IN && direct != FILTER_OUT)
3989 return BGP_ERR_INVALID_VALUE;
3990
3991 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3992 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3993
3994 filter = &peer->filter[afi][safi];
3995
3996 if (filter->aslist[direct].name)
3997 free (filter->aslist[direct].name);
3998 filter->aslist[direct].name = strdup (name);
3999 filter->aslist[direct].aslist = as_list_lookup (name);
4000
4001 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4002 return 0;
4003
4004 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004005 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004006 {
4007 filter = &peer->filter[afi][safi];
4008
4009 if (! peer->af_group[afi][safi])
4010 continue;
4011
4012 if (filter->aslist[direct].name)
4013 free (filter->aslist[direct].name);
4014 filter->aslist[direct].name = strdup (name);
4015 filter->aslist[direct].aslist = as_list_lookup (name);
4016 }
4017 return 0;
4018}
4019
4020int
4021peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4022{
4023 struct bgp_filter *filter;
4024 struct bgp_filter *gfilter;
4025 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004026 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004027
4028 if (! peer->afc[afi][safi])
4029 return BGP_ERR_PEER_INACTIVE;
4030
hassob5f29602005-05-25 21:00:28 +00004031 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004032 return BGP_ERR_INVALID_VALUE;
4033
hassob5f29602005-05-25 21:00:28 +00004034 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004035 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4036
4037 filter = &peer->filter[afi][safi];
4038
4039 /* apply peer-group filter */
4040 if (peer->af_group[afi][safi])
4041 {
4042 gfilter = &peer->group->conf->filter[afi][safi];
4043
4044 if (gfilter->aslist[direct].name)
4045 {
4046 if (filter->aslist[direct].name)
4047 free (filter->aslist[direct].name);
4048 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4049 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4050 return 0;
4051 }
4052 }
4053
4054 if (filter->aslist[direct].name)
4055 free (filter->aslist[direct].name);
4056 filter->aslist[direct].name = NULL;
4057 filter->aslist[direct].aslist = NULL;
4058
4059 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4060 return 0;
4061
4062 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004063 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004064 {
4065 filter = &peer->filter[afi][safi];
4066
4067 if (! peer->af_group[afi][safi])
4068 continue;
4069
4070 if (filter->aslist[direct].name)
4071 free (filter->aslist[direct].name);
4072 filter->aslist[direct].name = NULL;
4073 filter->aslist[direct].aslist = NULL;
4074 }
4075
4076 return 0;
4077}
4078
paul94f2b392005-06-28 12:44:16 +00004079static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004080peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004081{
4082 afi_t afi;
4083 safi_t safi;
4084 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004085 struct listnode *mnode, *mnnode;
4086 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004087 struct bgp *bgp;
4088 struct peer *peer;
4089 struct peer_group *group;
4090 struct bgp_filter *filter;
4091
paul1eb8ef22005-04-07 07:30:20 +00004092 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004093 {
paul1eb8ef22005-04-07 07:30:20 +00004094 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004095 {
4096 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4097 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4098 {
4099 filter = &peer->filter[afi][safi];
4100
4101 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4102 {
4103 if (filter->aslist[direct].name)
4104 filter->aslist[direct].aslist =
4105 as_list_lookup (filter->aslist[direct].name);
4106 else
4107 filter->aslist[direct].aslist = NULL;
4108 }
4109 }
4110 }
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004112 {
4113 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4114 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4115 {
4116 filter = &group->conf->filter[afi][safi];
4117
4118 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4119 {
4120 if (filter->aslist[direct].name)
4121 filter->aslist[direct].aslist =
4122 as_list_lookup (filter->aslist[direct].name);
4123 else
4124 filter->aslist[direct].aslist = NULL;
4125 }
4126 }
4127 }
4128 }
4129}
4130
4131/* Set route-map to the peer. */
4132int
4133peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004134 const char *name)
paul718e3742002-12-13 20:15:29 +00004135{
4136 struct bgp_filter *filter;
4137 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004138 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004139
4140 if (! peer->afc[afi][safi])
4141 return BGP_ERR_PEER_INACTIVE;
4142
paulfee0f4c2004-09-13 05:12:46 +00004143 if (direct != RMAP_IN && direct != RMAP_OUT &&
4144 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004145 return BGP_ERR_INVALID_VALUE;
4146
paulfee0f4c2004-09-13 05:12:46 +00004147 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4148 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004149 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4150
4151 filter = &peer->filter[afi][safi];
4152
4153 if (filter->map[direct].name)
4154 free (filter->map[direct].name);
4155
4156 filter->map[direct].name = strdup (name);
4157 filter->map[direct].map = route_map_lookup_by_name (name);
4158
4159 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4160 return 0;
4161
4162 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004163 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004164 {
4165 filter = &peer->filter[afi][safi];
4166
4167 if (! peer->af_group[afi][safi])
4168 continue;
4169
4170 if (filter->map[direct].name)
4171 free (filter->map[direct].name);
4172 filter->map[direct].name = strdup (name);
4173 filter->map[direct].map = route_map_lookup_by_name (name);
4174 }
4175 return 0;
4176}
4177
4178/* Unset route-map from the peer. */
4179int
4180peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4181{
4182 struct bgp_filter *filter;
4183 struct bgp_filter *gfilter;
4184 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004185 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004186
4187 if (! peer->afc[afi][safi])
4188 return BGP_ERR_PEER_INACTIVE;
4189
hassob5f29602005-05-25 21:00:28 +00004190 if (direct != RMAP_IN && direct != RMAP_OUT &&
4191 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004192 return BGP_ERR_INVALID_VALUE;
4193
hassob5f29602005-05-25 21:00:28 +00004194 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4195 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004196 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4197
4198 filter = &peer->filter[afi][safi];
4199
4200 /* apply peer-group filter */
4201 if (peer->af_group[afi][safi])
4202 {
4203 gfilter = &peer->group->conf->filter[afi][safi];
4204
4205 if (gfilter->map[direct].name)
4206 {
4207 if (filter->map[direct].name)
4208 free (filter->map[direct].name);
4209 filter->map[direct].name = strdup (gfilter->map[direct].name);
4210 filter->map[direct].map = gfilter->map[direct].map;
4211 return 0;
4212 }
4213 }
4214
4215 if (filter->map[direct].name)
4216 free (filter->map[direct].name);
4217 filter->map[direct].name = NULL;
4218 filter->map[direct].map = NULL;
4219
4220 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4221 return 0;
4222
4223 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004224 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004225 {
4226 filter = &peer->filter[afi][safi];
4227
4228 if (! peer->af_group[afi][safi])
4229 continue;
4230
4231 if (filter->map[direct].name)
4232 free (filter->map[direct].name);
4233 filter->map[direct].name = NULL;
4234 filter->map[direct].map = NULL;
4235 }
4236 return 0;
4237}
4238
4239/* Set unsuppress-map to the peer. */
4240int
paulfd79ac92004-10-13 05:06:08 +00004241peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4242 const char *name)
paul718e3742002-12-13 20:15:29 +00004243{
4244 struct bgp_filter *filter;
4245 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004246 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004247
4248 if (! peer->afc[afi][safi])
4249 return BGP_ERR_PEER_INACTIVE;
4250
4251 if (peer_is_group_member (peer, afi, safi))
4252 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4253
4254 filter = &peer->filter[afi][safi];
4255
4256 if (filter->usmap.name)
4257 free (filter->usmap.name);
4258
4259 filter->usmap.name = strdup (name);
4260 filter->usmap.map = route_map_lookup_by_name (name);
4261
4262 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4263 return 0;
4264
4265 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004266 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004267 {
4268 filter = &peer->filter[afi][safi];
4269
4270 if (! peer->af_group[afi][safi])
4271 continue;
4272
4273 if (filter->usmap.name)
4274 free (filter->usmap.name);
4275 filter->usmap.name = strdup (name);
4276 filter->usmap.map = route_map_lookup_by_name (name);
4277 }
4278 return 0;
4279}
4280
4281/* Unset route-map from the peer. */
4282int
4283peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4284{
4285 struct bgp_filter *filter;
4286 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004287 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004288
4289 if (! peer->afc[afi][safi])
4290 return BGP_ERR_PEER_INACTIVE;
4291
4292 if (peer_is_group_member (peer, afi, safi))
4293 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4294
4295 filter = &peer->filter[afi][safi];
4296
4297 if (filter->usmap.name)
4298 free (filter->usmap.name);
4299 filter->usmap.name = NULL;
4300 filter->usmap.map = NULL;
4301
4302 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4303 return 0;
4304
4305 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004306 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004307 {
4308 filter = &peer->filter[afi][safi];
4309
4310 if (! peer->af_group[afi][safi])
4311 continue;
4312
4313 if (filter->usmap.name)
4314 free (filter->usmap.name);
4315 filter->usmap.name = NULL;
4316 filter->usmap.map = NULL;
4317 }
4318 return 0;
4319}
4320
4321int
4322peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004323 u_int32_t max, u_char threshold,
4324 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004325{
4326 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004327 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004328
4329 if (! peer->afc[afi][safi])
4330 return BGP_ERR_PEER_INACTIVE;
4331
4332 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4333 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004334 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004335 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004336 if (warning)
4337 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4338 else
4339 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4340
4341 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4342 return 0;
4343
4344 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004345 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004346 {
4347 if (! peer->af_group[afi][safi])
4348 continue;
4349
4350 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4351 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004352 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004353 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004354 if (warning)
4355 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4356 else
4357 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4358 }
4359 return 0;
4360}
4361
4362int
4363peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4364{
4365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004367
4368 if (! peer->afc[afi][safi])
4369 return BGP_ERR_PEER_INACTIVE;
4370
4371 /* apply peer-group config */
4372 if (peer->af_group[afi][safi])
4373 {
4374 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4375 PEER_FLAG_MAX_PREFIX))
4376 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4377 else
4378 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4379
4380 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4381 PEER_FLAG_MAX_PREFIX_WARNING))
4382 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4383 else
4384 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4385
4386 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004387 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004388 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004389 return 0;
4390 }
4391
4392 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4393 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4394 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004395 peer->pmax_threshold[afi][safi] = 0;
4396 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004397
4398 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4399 return 0;
4400
4401 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004402 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004403 {
4404 if (! peer->af_group[afi][safi])
4405 continue;
4406
4407 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4408 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4409 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004410 peer->pmax_threshold[afi][safi] = 0;
4411 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004412 }
4413 return 0;
4414}
David Lamparter5f9adb52014-05-19 23:15:02 +02004415
4416static int is_ebgp_multihop_configured (struct peer *peer)
4417{
4418 struct peer_group *group;
4419 struct listnode *node, *nnode;
4420 struct peer *peer1;
4421
4422 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4423 {
4424 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004425 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4426 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004427 return 1;
4428
4429 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4430 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004431 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4432 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004433 return 1;
4434 }
4435 }
4436 else
4437 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004438 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4439 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004440 return 1;
4441 }
4442 return 0;
4443}
4444
Nick Hilliardfa411a22011-03-23 15:33:17 +00004445/* Set # of hops between us and BGP peer. */
4446int
4447peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4448{
4449 struct peer_group *group;
4450 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004451 int ret;
4452
4453 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4454
Nick Hilliardfa411a22011-03-23 15:33:17 +00004455 /* We cannot configure ttl-security hops when ebgp-multihop is already
4456 set. For non peer-groups, the check is simple. For peer-groups, it's
4457 slightly messy, because we need to check both the peer-group structure
4458 and all peer-group members for any trace of ebgp-multihop configuration
4459 before actually applying the ttl-security rules. Cisco really made a
4460 mess of this configuration parameter, and OpenBGPD got it right.
4461 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004462
David Lamparter5f9adb52014-05-19 23:15:02 +02004463 if (peer->gtsm_hops == 0)
4464 {
4465 if (is_ebgp_multihop_configured (peer))
4466 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004467
David Lamparter5f9adb52014-05-19 23:15:02 +02004468 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004469 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004470 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4471 if (ret != 0)
4472 return ret;
4473 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004474
Nick Hilliardfa411a22011-03-23 15:33:17 +00004475 peer->gtsm_hops = gtsm_hops;
4476
Nick Hilliardfa411a22011-03-23 15:33:17 +00004477 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4478 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004479 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004480 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4481 }
4482 else
4483 {
4484 group = peer->group;
4485 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4486 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004487 peer->gtsm_hops = group->conf->gtsm_hops;
4488
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004489 /* Change setting of existing peer
4490 * established then change value (may break connectivity)
4491 * not established yet (teardown session and restart)
4492 * no session then do nothing (will get handled by next connection)
4493 */
4494 if (peer->status == Established)
4495 {
4496 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4497 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4498 MAXTTL + 1 - peer->gtsm_hops);
4499 }
4500 else if (peer->status < Established)
4501 {
4502 if (BGP_DEBUG (events, EVENTS))
4503 zlog_debug ("%s Min-ttl changed", peer->host);
4504 BGP_EVENT_ADD (peer, BGP_Stop);
4505 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004506 }
4507 }
4508
4509 return 0;
4510}
4511
4512int
4513peer_ttl_security_hops_unset (struct peer *peer)
4514{
4515 struct peer_group *group;
4516 struct listnode *node, *nnode;
4517 struct peer *opeer;
4518
4519 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4520
Nick Hilliardfa411a22011-03-23 15:33:17 +00004521 /* if a peer-group member, then reset to peer-group default rather than 0 */
4522 if (peer_group_active (peer))
4523 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4524 else
4525 peer->gtsm_hops = 0;
4526
4527 opeer = peer;
4528 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4529 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004530 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004531 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4532 }
4533 else
4534 {
4535 group = peer->group;
4536 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4537 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004538 peer->gtsm_hops = 0;
4539
4540 if (peer->fd >= 0)
4541 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4542 }
4543 }
4544
4545 return peer_ebgp_multihop_unset (opeer);
4546}
4547
paul718e3742002-12-13 20:15:29 +00004548int
4549peer_clear (struct peer *peer)
4550{
4551 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4552 {
hasso0a486e52005-02-01 20:57:17 +00004553 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4554 {
4555 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4556 if (peer->t_pmax_restart)
4557 {
4558 BGP_TIMER_OFF (peer->t_pmax_restart);
4559 if (BGP_DEBUG (events, EVENTS))
4560 zlog_debug ("%s Maximum-prefix restart timer canceled",
4561 peer->host);
4562 }
4563 BGP_EVENT_ADD (peer, BGP_Start);
4564 return 0;
4565 }
4566
paul718e3742002-12-13 20:15:29 +00004567 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004568 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004569 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4570 BGP_NOTIFY_CEASE_ADMIN_RESET);
4571 else
4572 BGP_EVENT_ADD (peer, BGP_Stop);
4573 }
4574 return 0;
4575}
4576
4577int
4578peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4579 enum bgp_clear_type stype)
4580{
4581 if (peer->status != Established)
4582 return 0;
4583
4584 if (! peer->afc[afi][safi])
4585 return BGP_ERR_AF_UNCONFIGURED;
4586
paulfee0f4c2004-09-13 05:12:46 +00004587 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4588 {
4589 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4590 return 0;
4591 bgp_check_local_routes_rsclient (peer, afi, safi);
4592 bgp_soft_reconfig_rsclient (peer, afi, safi);
4593 }
4594
paul718e3742002-12-13 20:15:29 +00004595 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4596 bgp_announce_route (peer, afi, safi);
4597
4598 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4599 {
4600 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4601 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4602 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4603 {
4604 struct bgp_filter *filter = &peer->filter[afi][safi];
4605 u_char prefix_type;
4606
4607 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4608 prefix_type = ORF_TYPE_PREFIX;
4609 else
4610 prefix_type = ORF_TYPE_PREFIX_OLD;
4611
4612 if (filter->plist[FILTER_IN].plist)
4613 {
4614 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4615 bgp_route_refresh_send (peer, afi, safi,
4616 prefix_type, REFRESH_DEFER, 1);
4617 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4618 REFRESH_IMMEDIATE, 0);
4619 }
4620 else
4621 {
4622 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4623 bgp_route_refresh_send (peer, afi, safi,
4624 prefix_type, REFRESH_IMMEDIATE, 1);
4625 else
4626 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4627 }
4628 return 0;
4629 }
4630 }
4631
4632 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4633 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4634 {
4635 /* If neighbor has soft reconfiguration inbound flag.
4636 Use Adj-RIB-In database. */
4637 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4638 bgp_soft_reconfig_in (peer, afi, safi);
4639 else
4640 {
4641 /* If neighbor has route refresh capability, send route refresh
4642 message to the peer. */
4643 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4644 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4645 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4646 else
4647 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4648 }
4649 }
4650 return 0;
4651}
4652
paulfd79ac92004-10-13 05:06:08 +00004653/* Display peer uptime.*/
4654/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004655char *
4656peer_uptime (time_t uptime2, char *buf, size_t len)
4657{
4658 time_t uptime1;
4659 struct tm *tm;
4660
4661 /* Check buffer length. */
4662 if (len < BGP_UPTIME_LEN)
4663 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004664 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004665 /* XXX: should return status instead of buf... */
4666 snprintf (buf, len, "<error> ");
4667 return buf;
paul718e3742002-12-13 20:15:29 +00004668 }
4669
4670 /* If there is no connection has been done before print `never'. */
4671 if (uptime2 == 0)
4672 {
4673 snprintf (buf, len, "never ");
4674 return buf;
4675 }
4676
4677 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004678 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004679 uptime1 -= uptime2;
4680 tm = gmtime (&uptime1);
4681
4682 /* Making formatted timer strings. */
4683#define ONE_DAY_SECOND 60*60*24
4684#define ONE_WEEK_SECOND 60*60*24*7
4685
4686 if (uptime1 < ONE_DAY_SECOND)
4687 snprintf (buf, len, "%02d:%02d:%02d",
4688 tm->tm_hour, tm->tm_min, tm->tm_sec);
4689 else if (uptime1 < ONE_WEEK_SECOND)
4690 snprintf (buf, len, "%dd%02dh%02dm",
4691 tm->tm_yday, tm->tm_hour, tm->tm_min);
4692 else
4693 snprintf (buf, len, "%02dw%dd%02dh",
4694 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4695 return buf;
4696}
4697
paul94f2b392005-06-28 12:44:16 +00004698static void
paul718e3742002-12-13 20:15:29 +00004699bgp_config_write_filter (struct vty *vty, struct peer *peer,
4700 afi_t afi, safi_t safi)
4701{
4702 struct bgp_filter *filter;
4703 struct bgp_filter *gfilter = NULL;
4704 char *addr;
4705 int in = FILTER_IN;
4706 int out = FILTER_OUT;
4707
4708 addr = peer->host;
4709 filter = &peer->filter[afi][safi];
4710 if (peer->af_group[afi][safi])
4711 gfilter = &peer->group->conf->filter[afi][safi];
4712
4713 /* distribute-list. */
4714 if (filter->dlist[in].name)
4715 if (! gfilter || ! gfilter->dlist[in].name
4716 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4717 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4718 filter->dlist[in].name, VTY_NEWLINE);
4719 if (filter->dlist[out].name && ! gfilter)
4720 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4721 filter->dlist[out].name, VTY_NEWLINE);
4722
4723 /* prefix-list. */
4724 if (filter->plist[in].name)
4725 if (! gfilter || ! gfilter->plist[in].name
4726 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4727 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4728 filter->plist[in].name, VTY_NEWLINE);
4729 if (filter->plist[out].name && ! gfilter)
4730 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4731 filter->plist[out].name, VTY_NEWLINE);
4732
4733 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004734 if (filter->map[RMAP_IN].name)
4735 if (! gfilter || ! gfilter->map[RMAP_IN].name
4736 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004737 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004738 filter->map[RMAP_IN].name, VTY_NEWLINE);
4739 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004740 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004741 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4742 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4743 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4744 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4745 if (filter->map[RMAP_EXPORT].name)
4746 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4747 || strcmp (filter->map[RMAP_EXPORT].name,
4748 gfilter->map[RMAP_EXPORT].name) != 0)
4749 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4750 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004751
4752 /* unsuppress-map */
4753 if (filter->usmap.name && ! gfilter)
4754 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4755 filter->usmap.name, VTY_NEWLINE);
4756
4757 /* filter-list. */
4758 if (filter->aslist[in].name)
4759 if (! gfilter || ! gfilter->aslist[in].name
4760 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4761 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4762 filter->aslist[in].name, VTY_NEWLINE);
4763 if (filter->aslist[out].name && ! gfilter)
4764 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4765 filter->aslist[out].name, VTY_NEWLINE);
4766}
4767
4768/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004769static void
paul718e3742002-12-13 20:15:29 +00004770bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4771 struct peer *peer, afi_t afi, safi_t safi)
4772{
paul718e3742002-12-13 20:15:29 +00004773 struct peer *g_peer = NULL;
4774 char buf[SU_ADDRSTRLEN];
4775 char *addr;
4776
paul718e3742002-12-13 20:15:29 +00004777 addr = peer->host;
4778 if (peer_group_active (peer))
4779 g_peer = peer->group->conf;
4780
4781 /************************************
4782 ****** Global to the neighbor ******
4783 ************************************/
4784 if (afi == AFI_IP && safi == SAFI_UNICAST)
4785 {
4786 /* remote-as. */
4787 if (! peer_group_active (peer))
4788 {
4789 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4790 vty_out (vty, " neighbor %s peer-group%s", addr,
4791 VTY_NEWLINE);
4792 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004793 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004794 VTY_NEWLINE);
4795 }
4796 else
4797 {
4798 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004799 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004800 VTY_NEWLINE);
4801 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4802 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4803 peer->group->name, VTY_NEWLINE);
4804 }
4805
4806 /* local-as. */
4807 if (peer->change_local_as)
4808 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004809 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004810 peer->change_local_as,
4811 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004812 " no-prepend" : "",
4813 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4814 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004815
4816 /* Description. */
4817 if (peer->desc)
4818 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4819 VTY_NEWLINE);
4820
4821 /* Shutdown. */
4822 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4823 if (! peer_group_active (peer) ||
4824 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4825 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4826
Paul Jakma0df7c912008-07-21 21:02:49 +00004827 /* Password. */
4828 if (peer->password)
4829 if (!peer_group_active (peer)
4830 || ! g_peer->password
4831 || strcmp (peer->password, g_peer->password) != 0)
4832 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4833 VTY_NEWLINE);
4834
paul718e3742002-12-13 20:15:29 +00004835 /* BGP port. */
4836 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004837 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004838 VTY_NEWLINE);
4839
4840 /* Local interface name. */
4841 if (peer->ifname)
4842 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4843 VTY_NEWLINE);
4844
4845 /* Passive. */
4846 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4847 if (! peer_group_active (peer) ||
4848 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4849 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4850
4851 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004852 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004853 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004854 if (! peer_group_active (peer) ||
4855 g_peer->ttl != peer->ttl)
4856 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4857 VTY_NEWLINE);
4858
Nick Hilliardfa411a22011-03-23 15:33:17 +00004859 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004860 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004861 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004862 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004863 peer->gtsm_hops, VTY_NEWLINE);
4864
hasso6ffd2072005-02-02 14:50:11 +00004865 /* disable-connected-check. */
4866 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004867 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004868 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4869 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004870
4871 /* Update-source. */
4872 if (peer->update_if)
4873 if (! peer_group_active (peer) || ! g_peer->update_if
4874 || strcmp (g_peer->update_if, peer->update_if) != 0)
4875 vty_out (vty, " neighbor %s update-source %s%s", addr,
4876 peer->update_if, VTY_NEWLINE);
4877 if (peer->update_source)
4878 if (! peer_group_active (peer) || ! g_peer->update_source
4879 || sockunion_cmp (g_peer->update_source,
4880 peer->update_source) != 0)
4881 vty_out (vty, " neighbor %s update-source %s%s", addr,
4882 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4883 VTY_NEWLINE);
4884
paul718e3742002-12-13 20:15:29 +00004885 /* advertisement-interval */
4886 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4887 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4888 addr, peer->v_routeadv, VTY_NEWLINE);
4889
4890 /* timers. */
4891 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4892 && ! peer_group_active (peer))
4893 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4894 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4895
4896 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4897 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4898 peer->connect, VTY_NEWLINE);
4899
4900 /* Default weight. */
4901 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4902 if (! peer_group_active (peer) ||
4903 g_peer->weight != peer->weight)
4904 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4905 VTY_NEWLINE);
4906
paul718e3742002-12-13 20:15:29 +00004907 /* Dynamic capability. */
4908 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4909 if (! peer_group_active (peer) ||
4910 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4911 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4912 VTY_NEWLINE);
4913
4914 /* dont capability negotiation. */
4915 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4916 if (! peer_group_active (peer) ||
4917 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4918 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4919 VTY_NEWLINE);
4920
4921 /* override capability negotiation. */
4922 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4923 if (! peer_group_active (peer) ||
4924 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4925 vty_out (vty, " neighbor %s override-capability%s", addr,
4926 VTY_NEWLINE);
4927
4928 /* strict capability negotiation. */
4929 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4930 if (! peer_group_active (peer) ||
4931 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4932 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4933 VTY_NEWLINE);
4934
Christian Franke15c71342012-11-19 11:17:31 +00004935 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004936 {
4937 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4938 {
4939 if (peer->afc[AFI_IP][SAFI_UNICAST])
4940 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4941 }
4942 else
4943 {
4944 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4945 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4946 }
4947 }
4948 }
4949
4950
4951 /************************************
4952 ****** Per AF to the neighbor ******
4953 ************************************/
4954
4955 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4956 {
4957 if (peer->af_group[afi][safi])
4958 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4959 peer->group->name, VTY_NEWLINE);
4960 else
4961 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4962 }
4963
4964 /* ORF capability. */
4965 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4966 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4967 if (! peer->af_group[afi][safi])
4968 {
4969 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4970
4971 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4972 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4973 vty_out (vty, " both");
4974 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4975 vty_out (vty, " send");
4976 else
4977 vty_out (vty, " receive");
4978 vty_out (vty, "%s", VTY_NEWLINE);
4979 }
4980
4981 /* Route reflector client. */
4982 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4983 && ! peer->af_group[afi][safi])
4984 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4985 VTY_NEWLINE);
4986
4987 /* Nexthop self. */
4988 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4989 && ! peer->af_group[afi][safi])
4990 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4991
4992 /* Remove private AS. */
4993 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4994 && ! peer->af_group[afi][safi])
4995 vty_out (vty, " neighbor %s remove-private-AS%s",
4996 addr, VTY_NEWLINE);
4997
4998 /* send-community print. */
4999 if (! peer->af_group[afi][safi])
5000 {
5001 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5002 {
5003 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5004 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5005 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5006 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5007 vty_out (vty, " neighbor %s send-community extended%s",
5008 addr, VTY_NEWLINE);
5009 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5010 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5011 }
5012 else
5013 {
5014 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5015 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5016 vty_out (vty, " no neighbor %s send-community both%s",
5017 addr, VTY_NEWLINE);
5018 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5019 vty_out (vty, " no neighbor %s send-community extended%s",
5020 addr, VTY_NEWLINE);
5021 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5022 vty_out (vty, " no neighbor %s send-community%s",
5023 addr, VTY_NEWLINE);
5024 }
5025 }
5026
5027 /* Default information */
5028 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5029 && ! peer->af_group[afi][safi])
5030 {
5031 vty_out (vty, " neighbor %s default-originate", addr);
5032 if (peer->default_rmap[afi][safi].name)
5033 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5034 vty_out (vty, "%s", VTY_NEWLINE);
5035 }
5036
5037 /* Soft reconfiguration inbound. */
5038 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5039 if (! peer->af_group[afi][safi] ||
5040 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5041 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5042 VTY_NEWLINE);
5043
5044 /* maximum-prefix. */
5045 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5046 if (! peer->af_group[afi][safi]
5047 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005048 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005049 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5050 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005051 {
hasso0a486e52005-02-01 20:57:17 +00005052 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5053 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5054 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5055 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5056 vty_out (vty, " warning-only");
5057 if (peer->pmax_restart[afi][safi])
5058 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5059 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005060 }
paul718e3742002-12-13 20:15:29 +00005061
5062 /* Route server client. */
5063 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5064 && ! peer->af_group[afi][safi])
5065 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5066
Dylan Hall3cf12882011-10-27 15:28:17 +04005067 /* Nexthop-local unchanged. */
5068 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5069 && ! peer->af_group[afi][safi])
5070 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5071
paul718e3742002-12-13 20:15:29 +00005072 /* Allow AS in. */
5073 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5074 if (! peer_group_active (peer)
5075 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5076 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5077 {
5078 if (peer->allowas_in[afi][safi] == 3)
5079 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5080 else
5081 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5082 peer->allowas_in[afi][safi], VTY_NEWLINE);
5083 }
5084
5085 /* Filter. */
5086 bgp_config_write_filter (vty, peer, afi, safi);
5087
5088 /* atribute-unchanged. */
5089 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5090 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5091 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5092 && ! peer->af_group[afi][safi])
5093 {
5094 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5095 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5096 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5097 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5098 else
5099 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5100 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5101 " as-path" : "",
5102 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5103 " next-hop" : "",
5104 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5105 " med" : "", VTY_NEWLINE);
5106 }
5107}
5108
5109/* Display "address-family" configuration header. */
5110void
5111bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5112 int *write)
5113{
5114 if (*write)
5115 return;
5116
5117 if (afi == AFI_IP && safi == SAFI_UNICAST)
5118 return;
5119
5120 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5121
5122 if (afi == AFI_IP)
5123 {
5124 if (safi == SAFI_MULTICAST)
5125 vty_out (vty, "ipv4 multicast");
5126 else if (safi == SAFI_MPLS_VPN)
5127 vty_out (vty, "vpnv4 unicast");
5128 }
5129 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005130 {
5131 vty_out (vty, "ipv6");
5132
5133 if (safi == SAFI_MULTICAST)
5134 vty_out (vty, " multicast");
5135 }
paul718e3742002-12-13 20:15:29 +00005136
5137 vty_out (vty, "%s", VTY_NEWLINE);
5138
5139 *write = 1;
5140}
5141
5142/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005143static int
paul718e3742002-12-13 20:15:29 +00005144bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5145 safi_t safi)
5146{
5147 int write = 0;
5148 struct peer *peer;
5149 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005150 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005151
5152 bgp_config_write_network (vty, bgp, afi, safi, &write);
5153
5154 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5155
paul1eb8ef22005-04-07 07:30:20 +00005156 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005157 {
5158 if (group->conf->afc[afi][safi])
5159 {
5160 bgp_config_write_family_header (vty, afi, safi, &write);
5161 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5162 }
5163 }
paul1eb8ef22005-04-07 07:30:20 +00005164 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005165 {
5166 if (peer->afc[afi][safi])
5167 {
5168 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5169 {
5170 bgp_config_write_family_header (vty, afi, safi, &write);
5171 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5172 }
5173 }
5174 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005175
5176 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5177
paul718e3742002-12-13 20:15:29 +00005178 if (write)
5179 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5180
5181 return write;
5182}
5183
5184int
5185bgp_config_write (struct vty *vty)
5186{
5187 int write = 0;
5188 struct bgp *bgp;
5189 struct peer_group *group;
5190 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005191 struct listnode *node, *nnode;
5192 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005193
5194 /* BGP Multiple instance. */
5195 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5196 {
5197 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5198 write++;
5199 }
5200
5201 /* BGP Config type. */
5202 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5203 {
5204 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5205 write++;
5206 }
5207
5208 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005209 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005210 {
5211 if (write)
5212 vty_out (vty, "!%s", VTY_NEWLINE);
5213
5214 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005215 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005216
5217 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5218 {
5219 if (bgp->name)
5220 vty_out (vty, " view %s", bgp->name);
5221 }
5222 vty_out (vty, "%s", VTY_NEWLINE);
5223
5224 /* No Synchronization */
5225 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5226 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5227
5228 /* BGP fast-external-failover. */
5229 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5230 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5231
5232 /* BGP router ID. */
5233 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5234 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5235 VTY_NEWLINE);
5236
paul848973c2003-08-13 00:32:49 +00005237 /* BGP log-neighbor-changes. */
5238 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5239 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5240
paul718e3742002-12-13 20:15:29 +00005241 /* BGP configuration. */
5242 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5243 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5244
5245 /* BGP default ipv4-unicast. */
5246 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5247 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5248
5249 /* BGP default local-preference. */
5250 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5251 vty_out (vty, " bgp default local-preference %d%s",
5252 bgp->default_local_pref, VTY_NEWLINE);
5253
5254 /* BGP client-to-client reflection. */
5255 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5256 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5257
5258 /* BGP cluster ID. */
5259 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5260 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5261 VTY_NEWLINE);
5262
hassoe0701b72004-05-20 09:19:34 +00005263 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005264 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005265 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5266 VTY_NEWLINE);
5267
5268 /* Confederation peer */
5269 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005270 {
hassoe0701b72004-05-20 09:19:34 +00005271 int i;
paul718e3742002-12-13 20:15:29 +00005272
hassoe0701b72004-05-20 09:19:34 +00005273 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005274
hassoe0701b72004-05-20 09:19:34 +00005275 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005276 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005277
hassoe0701b72004-05-20 09:19:34 +00005278 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005279 }
5280
5281 /* BGP enforce-first-as. */
5282 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5283 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5284
5285 /* BGP deterministic-med. */
5286 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5287 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005288
5289 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005290 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5291 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5292 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005293 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5294 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5295
paul718e3742002-12-13 20:15:29 +00005296 /* BGP bestpath method. */
5297 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5298 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005299 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5300 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005301 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5302 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5303 }
paul718e3742002-12-13 20:15:29 +00005304 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5305 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5306 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5307 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5308 {
5309 vty_out (vty, " bgp bestpath med");
5310 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5311 vty_out (vty, " confed");
5312 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5313 vty_out (vty, " missing-as-worst");
5314 vty_out (vty, "%s", VTY_NEWLINE);
5315 }
5316
5317 /* BGP network import check. */
5318 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5319 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5320
5321 /* BGP scan interval. */
5322 bgp_config_write_scan_time (vty);
5323
5324 /* BGP flag dampening. */
5325 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5326 BGP_CONFIG_DAMPENING))
5327 bgp_config_write_damp (vty);
5328
5329 /* BGP static route configuration. */
5330 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5331
5332 /* BGP redistribute configuration. */
5333 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5334
5335 /* BGP timers configuration. */
5336 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5337 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5338 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5339 bgp->default_holdtime, VTY_NEWLINE);
5340
5341 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005342 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005343 {
5344 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5345 }
5346
5347 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005349 {
5350 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5351 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5352 }
5353
Josh Bailey165b5ff2011-07-20 20:43:22 -07005354 /* maximum-paths */
5355 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5356
paul718e3742002-12-13 20:15:29 +00005357 /* Distance configuration. */
5358 bgp_config_write_distance (vty, bgp);
5359
5360 /* No auto-summary */
5361 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5362 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5363
5364 /* IPv4 multicast configuration. */
5365 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5366
5367 /* IPv4 VPN configuration. */
5368 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5369
5370 /* IPv6 unicast configuration. */
5371 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5372
Paul Jakma37a217a2007-04-10 19:20:29 +00005373 /* IPv6 multicast configuration. */
5374 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5375
paul718e3742002-12-13 20:15:29 +00005376 write++;
5377 }
5378 return write;
5379}
5380
5381void
paul94f2b392005-06-28 12:44:16 +00005382bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005383{
5384 memset (&bgp_master, 0, sizeof (struct bgp_master));
5385
5386 bm = &bgp_master;
5387 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005388 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005389 bm->port = BGP_PORT_DEFAULT;
5390 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005391 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005392}
paul200df112005-06-01 11:17:05 +00005393
paul718e3742002-12-13 20:15:29 +00005394
5395void
paul94f2b392005-06-28 12:44:16 +00005396bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005397{
paul718e3742002-12-13 20:15:29 +00005398 /* BGP VTY commands installation. */
5399 bgp_vty_init ();
5400
paul718e3742002-12-13 20:15:29 +00005401 /* Init zebra. */
5402 bgp_zebra_init ();
5403
5404 /* BGP inits. */
5405 bgp_attr_init ();
5406 bgp_debug_init ();
5407 bgp_dump_init ();
5408 bgp_route_init ();
5409 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005410 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005411 bgp_scan_init ();
5412 bgp_mplsvpn_init ();
5413
5414 /* Access list initialize. */
5415 access_list_init ();
5416 access_list_add_hook (peer_distribute_update);
5417 access_list_delete_hook (peer_distribute_update);
5418
5419 /* Filter list initialize. */
5420 bgp_filter_init ();
5421 as_list_add_hook (peer_aslist_update);
5422 as_list_delete_hook (peer_aslist_update);
5423
5424 /* Prefix list initialize.*/
5425 prefix_list_init ();
5426 prefix_list_add_hook (peer_prefix_list_update);
5427 prefix_list_delete_hook (peer_prefix_list_update);
5428
5429 /* Community list initialize. */
5430 bgp_clist = community_list_init ();
5431
5432#ifdef HAVE_SNMP
5433 bgp_snmp_init ();
5434#endif /* HAVE_SNMP */
5435}
paul545acaf2004-04-20 15:13:15 +00005436
5437void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005438bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005439{
paul545acaf2004-04-20 15:13:15 +00005440 struct bgp *bgp;
5441 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005442 struct listnode *node, *nnode;
5443 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005444
paul1eb8ef22005-04-07 07:30:20 +00005445 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5446 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005447 if (peer->status == Established)
5448 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5449 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005450
paul545acaf2004-04-20 15:13:15 +00005451 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005452
paule210cf92005-06-15 19:15:35 +00005453 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005454 {
5455 work_queue_free (bm->process_main_queue);
5456 bm->process_main_queue = NULL;
5457 }
paule210cf92005-06-15 19:15:35 +00005458 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005459 {
5460 work_queue_free (bm->process_rsclient_queue);
5461 bm->process_rsclient_queue = NULL;
5462 }
paul545acaf2004-04-20 15:13:15 +00005463}