]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
ripd: set IP TOS for control socket
[mirror_frr.git] / bgpd / bgpd.c
CommitLineData
718e3744 1/* 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"
200df115 37#include "workqueue.h"
718e3744 38
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63\f
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
18a6dce6 67extern struct in_addr router_id_zebra;
68
718e3744 69/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74\f
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
718e3744 88 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
718e3744 107 }
108 return 0;
109}
110
111int
112bgp_option_check (int flag)
113{
114 return CHECK_FLAG (bm->options, flag);
115}
116\f
117/* BGP flag manipulation. */
118int
119bgp_flag_set (struct bgp *bgp, int flag)
120{
121 SET_FLAG (bgp->flags, flag);
122 return 0;
123}
124
125int
126bgp_flag_unset (struct bgp *bgp, int flag)
127{
128 UNSET_FLAG (bgp->flags, flag);
129 return 0;
130}
131
132int
133bgp_flag_check (struct bgp *bgp, int flag)
134{
135 return CHECK_FLAG (bgp->flags, flag);
136}
137\f
138/* Internal function to set BGP structure configureation flag. */
139static void
140bgp_config_set (struct bgp *bgp, int config)
141{
142 SET_FLAG (bgp->config, config);
143}
144
145static void
146bgp_config_unset (struct bgp *bgp, int config)
147{
148 UNSET_FLAG (bgp->config, config);
149}
150
151static int
152bgp_config_check (struct bgp *bgp, int config)
153{
154 return CHECK_FLAG (bgp->config, config);
155}
156\f
157/* Set BGP router identifier. */
158int
159bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
160{
161 struct peer *peer;
1eb8ef25 162 struct listnode *node, *nnode;
718e3744 163
164 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
165 && IPV4_ADDR_SAME (&bgp->router_id, id))
166 return 0;
167
168 IPV4_ADDR_COPY (&bgp->router_id, id);
169 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
170
171 /* Set all peer's local identifier with this value. */
1eb8ef25 172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 173 {
174 IPV4_ADDR_COPY (&peer->local_id, id);
175
176 if (peer->status == Established)
e0701b79 177 {
178 peer->last_reset = PEER_DOWN_RID_CHANGE;
179 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
180 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
181 }
718e3744 182 }
183 return 0;
184}
185
718e3744 186/* BGP's cluster-id control. */
187int
188bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
189{
190 struct peer *peer;
1eb8ef25 191 struct listnode *node, *nnode;
718e3744 192
193 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
194 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
195 return 0;
196
197 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
198 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
199
200 /* Clear all IBGP peer. */
1eb8ef25 201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 202 {
203 if (peer_sort (peer) != BGP_PEER_IBGP)
204 continue;
205
206 if (peer->status == Established)
e0701b79 207 {
208 peer->last_reset = PEER_DOWN_CLID_CHANGE;
209 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
210 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
211 }
718e3744 212 }
213 return 0;
214}
215
216int
217bgp_cluster_id_unset (struct bgp *bgp)
218{
219 struct peer *peer;
1eb8ef25 220 struct listnode *node, *nnode;
718e3744 221
222 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
223 return 0;
224
225 bgp->cluster_id.s_addr = 0;
226 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
227
228 /* Clear all IBGP peer. */
1eb8ef25 229 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 230 {
231 if (peer_sort (peer) != BGP_PEER_IBGP)
232 continue;
233
234 if (peer->status == Established)
e0701b79 235 {
236 peer->last_reset = PEER_DOWN_CLID_CHANGE;
237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
239 }
718e3744 240 }
241 return 0;
242}
243\f
244/* BGP timer configuration. */
245int
246bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
247{
248 bgp->default_keepalive = (keepalive < holdtime / 3
249 ? keepalive : holdtime / 3);
250 bgp->default_holdtime = holdtime;
251
252 return 0;
253}
254
255int
256bgp_timers_unset (struct bgp *bgp)
257{
258 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
259 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
260
261 return 0;
262}
263\f
264/* BGP confederation configuration. */
265int
266bgp_confederation_id_set (struct bgp *bgp, as_t as)
267{
268 struct peer *peer;
1eb8ef25 269 struct listnode *node, *nnode;
718e3744 270 int already_confed;
271
272 if (as == 0)
273 return BGP_ERR_INVALID_AS;
274
275 /* Remember - were we doing confederation before? */
276 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
277 bgp->confed_id = as;
278 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
279
280 /* If we were doing confederation already, this is just an external
281 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
282 were not doing confederation before, reset all EBGP sessions. */
1eb8ef25 283 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 284 {
285 /* We're looking for peers who's AS is not local or part of our
286 confederation. */
287 if (already_confed)
288 {
289 if (peer_sort (peer) == BGP_PEER_EBGP)
290 {
291 peer->local_as = as;
292 if (peer->status == Established)
e0701b79 293 {
294 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
295 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
297 }
298
718e3744 299 else
300 BGP_EVENT_ADD (peer, BGP_Stop);
301 }
302 }
303 else
304 {
305 /* Not doign confederation before, so reset every non-local
306 session */
307 if (peer_sort (peer) != BGP_PEER_IBGP)
308 {
309 /* Reset the local_as to be our EBGP one */
310 if (peer_sort (peer) == BGP_PEER_EBGP)
311 peer->local_as = as;
312 if (peer->status == Established)
e0701b79 313 {
314 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
315 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
316 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
317 }
718e3744 318 else
319 BGP_EVENT_ADD (peer, BGP_Stop);
320 }
321 }
322 }
323 return 0;
324}
325
326int
327bgp_confederation_id_unset (struct bgp *bgp)
328{
329 struct peer *peer;
1eb8ef25 330 struct listnode *node, *nnode;
718e3744 331
332 bgp->confed_id = 0;
333 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
334
1eb8ef25 335 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 336 {
337 /* We're looking for peers who's AS is not local */
338 if (peer_sort (peer) != BGP_PEER_IBGP)
339 {
340 peer->local_as = bgp->as;
341 if (peer->status == Established)
e0701b79 342 {
343 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
344 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
345 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
346 }
347
718e3744 348 else
349 BGP_EVENT_ADD (peer, BGP_Stop);
350 }
351 }
352 return 0;
353}
354
355/* Is an AS part of the confed or not? */
356int
357bgp_confederation_peers_check (struct bgp *bgp, as_t as)
358{
359 int i;
360
361 if (! bgp)
362 return 0;
363
364 for (i = 0; i < bgp->confed_peers_cnt; i++)
365 if (bgp->confed_peers[i] == as)
366 return 1;
367
368 return 0;
369}
370
371/* Add an AS to the confederation set. */
372int
373bgp_confederation_peers_add (struct bgp *bgp, as_t as)
374{
375 struct peer *peer;
1eb8ef25 376 struct listnode *node, *nnode;
718e3744 377
378 if (! bgp)
379 return BGP_ERR_INVALID_BGP;
380
381 if (bgp->as == as)
382 return BGP_ERR_INVALID_AS;
383
384 if (bgp_confederation_peers_check (bgp, as))
385 return -1;
386
387 if (bgp->confed_peers)
388 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
389 bgp->confed_peers,
390 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
391 else
392 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
393 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
394
395 bgp->confed_peers[bgp->confed_peers_cnt] = as;
396 bgp->confed_peers_cnt++;
397
398 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
399 {
1eb8ef25 400 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 401 {
402 if (peer->as == as)
403 {
404 peer->local_as = bgp->as;
405 if (peer->status == Established)
e0701b79 406 {
407 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
408 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
409 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
410 }
718e3744 411 else
412 BGP_EVENT_ADD (peer, BGP_Stop);
413 }
414 }
415 }
416 return 0;
417}
418
419/* Delete an AS from the confederation set. */
420int
421bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
422{
423 int i;
424 int j;
425 struct peer *peer;
1eb8ef25 426 struct listnode *node, *nnode;
718e3744 427
428 if (! bgp)
429 return -1;
430
431 if (! bgp_confederation_peers_check (bgp, as))
432 return -1;
433
434 for (i = 0; i < bgp->confed_peers_cnt; i++)
435 if (bgp->confed_peers[i] == as)
436 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
437 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
438
439 bgp->confed_peers_cnt--;
440
441 if (bgp->confed_peers_cnt == 0)
442 {
443 if (bgp->confed_peers)
444 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
445 bgp->confed_peers = NULL;
446 }
447 else
448 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
449 bgp->confed_peers,
450 bgp->confed_peers_cnt * sizeof (as_t));
451
452 /* Now reset any peer who's remote AS has just been removed from the
453 CONFED */
454 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
455 {
1eb8ef25 456 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 457 {
458 if (peer->as == as)
459 {
460 peer->local_as = bgp->confed_id;
461 if (peer->status == Established)
e0701b79 462 {
463 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
466 }
718e3744 467 else
468 BGP_EVENT_ADD (peer, BGP_Stop);
469 }
470 }
471 }
472
473 return 0;
474}
475\f
476/* Local preference configuration. */
477int
478bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
479{
480 if (! bgp)
481 return -1;
482
718e3744 483 bgp->default_local_pref = local_pref;
484
485 return 0;
486}
487
488int
489bgp_default_local_preference_unset (struct bgp *bgp)
490{
491 if (! bgp)
492 return -1;
493
718e3744 494 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
495
496 return 0;
497}
498\f
fee0f4c6 499/* If peer is RSERVER_CLIENT in at least one address family and is not member
500 of a peer_group for that family, return 1.
501 Used to check wether the peer is included in list bgp->rsclient. */
502int
503peer_rsclient_active (struct peer *peer)
504{
505 int i;
506 int j;
507
508 for (i=AFI_IP; i < AFI_MAX; i++)
509 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
510 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
511 && ! peer->af_group[i][j])
512 return 1;
513 return 0;
514}
515
eb821189 516/* Peer comparison function for sorting. */
718e3744 517static int
518peer_cmp (struct peer *p1, struct peer *p2)
519{
eb821189 520 return sockunion_cmp (&p1->su, &p2->su);
718e3744 521}
522
523int
524peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
525{
526 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
527}
528
529/* Reset all address family specific configuration. */
530static void
531peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
532{
533 int i;
534 struct bgp_filter *filter;
535 char orf_name[BUFSIZ];
536
537 filter = &peer->filter[afi][safi];
538
539 /* Clear neighbor filter and route-map */
540 for (i = FILTER_IN; i < FILTER_MAX; i++)
541 {
542 if (filter->dlist[i].name)
543 {
544 free (filter->dlist[i].name);
545 filter->dlist[i].name = NULL;
546 }
547 if (filter->plist[i].name)
548 {
549 free (filter->plist[i].name);
550 filter->plist[i].name = NULL;
551 }
552 if (filter->aslist[i].name)
553 {
554 free (filter->aslist[i].name);
555 filter->aslist[i].name = NULL;
556 }
fee0f4c6 557 }
558 for (i = RMAP_IN; i < RMAP_MAX; i++)
559 {
718e3744 560 if (filter->map[i].name)
561 {
562 free (filter->map[i].name);
563 filter->map[i].name = NULL;
564 }
565 }
566
567 /* Clear unsuppress map. */
568 if (filter->usmap.name)
569 free (filter->usmap.name);
570 filter->usmap.name = NULL;
571 filter->usmap.map = NULL;
572
573 /* Clear neighbor's all address family flags. */
574 peer->af_flags[afi][safi] = 0;
575
576 /* Clear neighbor's all address family sflags. */
577 peer->af_sflags[afi][safi] = 0;
578
579 /* Clear neighbor's all address family capabilities. */
580 peer->af_cap[afi][safi] = 0;
581
582 /* Clear ORF info */
583 peer->orf_plist[afi][safi] = NULL;
584 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
585 prefix_bgp_orf_remove_all (orf_name);
586
587 /* Set default neighbor send-community. */
588 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
589 {
590 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
592 }
593
594 /* Clear neighbor default_originate_rmap */
595 if (peer->default_rmap[afi][safi].name)
596 free (peer->default_rmap[afi][safi].name);
597 peer->default_rmap[afi][safi].name = NULL;
598 peer->default_rmap[afi][safi].map = NULL;
599
600 /* Clear neighbor maximum-prefix */
601 peer->pmax[afi][safi] = 0;
e0701b79 602 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
718e3744 603}
604
605/* peer global config reset */
94f2b392 606static void
718e3744 607peer_global_config_reset (struct peer *peer)
608{
609 peer->weight = 0;
610 peer->change_local_as = 0;
611 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
612 if (peer->update_source)
613 {
614 sockunion_free (peer->update_source);
615 peer->update_source = NULL;
616 }
617 if (peer->update_if)
618 {
619 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
620 peer->update_if = NULL;
621 }
622
623 if (peer_sort (peer) == BGP_PEER_IBGP)
624 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
625 else
626 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
627
628 peer->flags = 0;
629 peer->config = 0;
630 peer->holdtime = 0;
631 peer->keepalive = 0;
632 peer->connect = 0;
633 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
634}
635
636/* Check peer's AS number and determin is this peer IBGP or EBGP */
637int
638peer_sort (struct peer *peer)
639{
640 struct bgp *bgp;
641
642 bgp = peer->bgp;
643
644 /* Peer-group */
645 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
646 {
647 if (peer->as)
648 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
649 else
650 {
651 struct peer *peer1;
652 peer1 = listnode_head (peer->group->peer);
653 if (peer1)
654 return (peer1->local_as == peer1->as
655 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
656 }
657 return BGP_PEER_INTERNAL;
658 }
659
660 /* Normal peer */
661 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
662 {
663 if (peer->local_as == 0)
664 return BGP_PEER_INTERNAL;
665
666 if (peer->local_as == peer->as)
667 {
668 if (peer->local_as == bgp->confed_id)
669 return BGP_PEER_EBGP;
670 else
671 return BGP_PEER_IBGP;
672 }
673
674 if (bgp_confederation_peers_check (bgp, peer->as))
675 return BGP_PEER_CONFED;
676
677 return BGP_PEER_EBGP;
678 }
679 else
680 {
681 return (peer->local_as == 0
682 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
683 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
684 }
685}
686
200df115 687static inline void
688peer_free (struct peer *peer)
689{
ca058a30 690 assert (peer->status == Deleted);
0088b5dc
SH
691
692 bgp_unlock(peer->bgp);
693
ca058a30
PJ
694 /* this /ought/ to have been done already through bgp_stop earlier,
695 * but just to be sure..
696 */
697 bgp_timer_set (peer);
698 BGP_READ_OFF (peer->t_read);
699 BGP_WRITE_OFF (peer->t_write);
9fde6624 700 BGP_EVENT_FLUSH (peer);
ca058a30 701
200df115 702 if (peer->desc)
703 XFREE (MTYPE_PEER_DESC, peer->desc);
704
705 /* Free allocated host character. */
706 if (peer->host)
707 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
708
709 /* Update source configuration. */
710 if (peer->update_source)
711 sockunion_free (peer->update_source);
712
713 if (peer->update_if)
714 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
a625ca3c
PJ
715
716 if (peer->clear_node_queue)
717 work_queue_free (peer->clear_node_queue);
718
ca058a30 719 bgp_sync_delete (peer);
200df115 720 memset (peer, 0, sizeof (struct peer));
721
722 XFREE (MTYPE_BGP_PEER, peer);
723}
724
725/* increase reference count on a struct peer */
726struct peer *
727peer_lock (struct peer *peer)
728{
729 assert (peer && (peer->lock >= 0));
ca058a30 730
200df115 731 peer->lock++;
732
733 return peer;
734}
735
736/* decrease reference count on a struct peer
737 * struct peer is freed and NULL returned if last reference
738 */
739struct peer *
740peer_unlock (struct peer *peer)
741{
742 assert (peer && (peer->lock > 0));
743
744 peer->lock--;
745
746 if (peer->lock == 0)
747 {
748#if 0
749 zlog_debug ("unlocked and freeing");
750 zlog_backtrace (LOG_DEBUG);
751#endif
752 peer_free (peer);
753 return NULL;
754 }
755
756#if 0
757 if (peer->lock == 1)
758 {
759 zlog_debug ("unlocked to 1");
760 zlog_backtrace (LOG_DEBUG);
761 }
762#endif
763
764 return peer;
765}
766
767/* Allocate new peer object, implicitely locked. */
718e3744 768static struct peer *
6f58544d 769peer_new (struct bgp *bgp)
718e3744 770{
771 afi_t afi;
772 safi_t safi;
773 struct peer *peer;
774 struct servent *sp;
6f58544d
PJ
775
776 /* bgp argument is absolutely required */
777 assert (bgp);
778 if (!bgp)
779 return NULL;
780
718e3744 781 /* Allocate new peer. */
ca058a30 782 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
718e3744 783
784 /* Set default value. */
eb821189 785 peer->fd = -1;
718e3744 786 peer->v_start = BGP_INIT_START_TIMER;
787 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
788 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
789 peer->status = Idle;
790 peer->ostatus = Idle;
718e3744 791 peer->weight = 0;
0df7c91f 792 peer->password = NULL;
6f58544d 793 peer->bgp = bgp;
ca058a30 794 peer = peer_lock (peer); /* initial reference */
0088b5dc 795 bgp_lock (bgp);
718e3744 796
797 /* Set default flags. */
798 for (afi = AFI_IP; afi < AFI_MAX; afi++)
799 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
800 {
801 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
802 {
803 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
804 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
805 }
806 peer->orf_plist[afi][safi] = NULL;
807 }
808 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
809
810 /* Create buffers. */
811 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
812 peer->obuf = stream_fifo_new ();
813 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
814
815 bgp_sync_init (peer);
816
817 /* Get service port number. */
818 sp = getservbyname ("bgp", "tcp");
819 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
820
821 return peer;
822}
823
824/* Create new BGP peer. */
94f2b392 825static struct peer *
718e3744 826peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
827 as_t remote_as, afi_t afi, safi_t safi)
828{
829 int active;
830 struct peer *peer;
831 char buf[SU_ADDRSTRLEN];
832
6f58544d 833 peer = peer_new (bgp);
718e3744 834 peer->su = *su;
835 peer->local_as = local_as;
836 peer->as = remote_as;
837 peer->local_id = bgp->router_id;
838 peer->v_holdtime = bgp->default_holdtime;
839 peer->v_keepalive = bgp->default_keepalive;
840 if (peer_sort (peer) == BGP_PEER_IBGP)
841 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
842 else
843 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
200df115 844
845 peer = peer_lock (peer); /* bgp peer list reference */
718e3744 846 listnode_add_sort (bgp->peer, peer);
847
848 active = peer_active (peer);
849
850 if (afi && safi)
851 peer->afc[afi][safi] = 1;
852
853 /* Last read time set */
854 peer->readtime = time (NULL);
855
848973c7 856 /* Last reset time set */
857 peer->resettime = time (NULL);
858
718e3744 859 /* Default TTL set. */
860 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
861
862 /* Make peer's address string. */
863 sockunion2str (su, buf, SU_ADDRSTRLEN);
e83e2080 864 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
718e3744 865
866 /* Set up peer's events and timers. */
867 if (! active && peer_active (peer))
868 bgp_timer_set (peer);
869
870 return peer;
871}
872
eb821189 873/* Make accept BGP peer. Called from bgp_accept (). */
874struct peer *
875peer_create_accept (struct bgp *bgp)
876{
877 struct peer *peer;
878
6f58544d 879 peer = peer_new (bgp);
200df115 880
881 peer = peer_lock (peer); /* bgp peer list reference */
eb821189 882 listnode_add_sort (bgp->peer, peer);
883
884 return peer;
885}
886
718e3744 887/* Change peer's AS number. */
94f2b392 888static void
718e3744 889peer_as_change (struct peer *peer, as_t as)
890{
891 int type;
892
893 /* Stop peer. */
894 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
895 {
896 if (peer->status == Established)
e0701b79 897 {
898 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
901 }
718e3744 902 else
903 BGP_EVENT_ADD (peer, BGP_Stop);
904 }
905 type = peer_sort (peer);
906 peer->as = as;
907
848973c7 908 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
909 && ! bgp_confederation_peers_check (peer->bgp, as)
910 && peer->bgp->as != as)
911 peer->local_as = peer->bgp->confed_id;
912 else
913 peer->local_as = peer->bgp->as;
914
718e3744 915 /* Advertisement-interval reset */
916 if (peer_sort (peer) == BGP_PEER_IBGP)
917 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
918 else
919 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
920
921 /* TTL reset */
922 if (peer_sort (peer) == BGP_PEER_IBGP)
923 peer->ttl = 255;
924 else if (type == BGP_PEER_IBGP)
925 peer->ttl = 1;
926
927 /* reflector-client reset */
928 if (peer_sort (peer) != BGP_PEER_IBGP)
929 {
930 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
931 PEER_FLAG_REFLECTOR_CLIENT);
932 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
933 PEER_FLAG_REFLECTOR_CLIENT);
934 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
935 PEER_FLAG_REFLECTOR_CLIENT);
936 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
937 PEER_FLAG_REFLECTOR_CLIENT);
938 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
939 PEER_FLAG_REFLECTOR_CLIENT);
940 }
941
942 /* local-as reset */
943 if (peer_sort (peer) != BGP_PEER_EBGP)
944 {
945 peer->change_local_as = 0;
946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
947 }
948}
949
950/* If peer does not exist, create new one. If peer already exists,
951 set AS number to the peer. */
952int
953peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
954 afi_t afi, safi_t safi)
955{
956 struct peer *peer;
957 as_t local_as;
958
959 peer = peer_lookup (bgp, su);
960
961 if (peer)
962 {
963 /* When this peer is a member of peer-group. */
964 if (peer->group)
965 {
966 if (peer->group->conf->as)
967 {
968 /* Return peer group's AS number. */
969 *as = peer->group->conf->as;
970 return BGP_ERR_PEER_GROUP_MEMBER;
971 }
972 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
973 {
974 if (bgp->as != *as)
975 {
976 *as = peer->as;
977 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
978 }
979 }
980 else
981 {
982 if (bgp->as == *as)
983 {
984 *as = peer->as;
985 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
986 }
987 }
988 }
989
990 /* Existing peer's AS number change. */
991 if (peer->as != *as)
992 peer_as_change (peer, *as);
993 }
994 else
995 {
996
997 /* If the peer is not part of our confederation, and its not an
998 iBGP peer then spoof the source AS */
999 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1000 && ! bgp_confederation_peers_check (bgp, *as)
1001 && bgp->as != *as)
1002 local_as = bgp->confed_id;
1003 else
1004 local_as = bgp->as;
1005
1006 /* If this is IPv4 unicast configuration and "no bgp default
1007 ipv4-unicast" is specified. */
1008
1009 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1010 && afi == AFI_IP && safi == SAFI_UNICAST)
1011 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1012 else
1013 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1014 }
1015
1016 return 0;
1017}
1018
1019/* Activate the peer or peer group for specified AFI and SAFI. */
1020int
1021peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1022{
1023 int active;
1024
1025 if (peer->afc[afi][safi])
1026 return 0;
1027
1028 /* Activate the address family configuration. */
1029 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1030 peer->afc[afi][safi] = 1;
1031 else
1032 {
1033 active = peer_active (peer);
1034
1035 peer->afc[afi][safi] = 1;
1036
1037 if (! active && peer_active (peer))
1038 bgp_timer_set (peer);
1039 else
1040 {
1041 if (peer->status == Established)
1042 {
1043 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1044 {
1045 peer->afc_adv[afi][safi] = 1;
1046 bgp_capability_send (peer, afi, safi,
1047 CAPABILITY_CODE_MP,
1048 CAPABILITY_ACTION_SET);
1049 if (peer->afc_recv[afi][safi])
1050 {
1051 peer->afc_nego[afi][safi] = 1;
1052 bgp_announce_route (peer, afi, safi);
1053 }
1054 }
1055 else
e0701b79 1056 {
1057 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1058 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1059 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1060 }
718e3744 1061 }
1062 }
1063 }
1064 return 0;
1065}
1066
1067int
1068peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1069{
1070 struct peer_group *group;
1071 struct peer *peer1;
1eb8ef25 1072 struct listnode *node, *nnode;
718e3744 1073
1074 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1075 {
1076 group = peer->group;
1077
1eb8ef25 1078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
718e3744 1079 {
1080 if (peer1->af_group[afi][safi])
1081 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1082 }
1083 }
1084 else
1085 {
1086 if (peer->af_group[afi][safi])
1087 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1088 }
1089
1090 if (! peer->afc[afi][safi])
1091 return 0;
1092
1093 /* De-activate the address family configuration. */
1094 peer->afc[afi][safi] = 0;
1095 peer_af_flag_reset (peer, afi, safi);
1096
1097 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1098 {
1099 if (peer->status == Established)
1100 {
1101 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1102 {
1103 peer->afc_adv[afi][safi] = 0;
1104 peer->afc_nego[afi][safi] = 0;
1105
1106 if (peer_active_nego (peer))
1107 {
1108 bgp_capability_send (peer, afi, safi,
1109 CAPABILITY_CODE_MP,
1110 CAPABILITY_ACTION_UNSET);
228da428 1111 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
718e3744 1112 peer->pcount[afi][safi] = 0;
1113 }
1114 else
e0701b79 1115 {
1116 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1117 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1118 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1119 }
718e3744 1120 }
1121 else
e0701b79 1122 {
1123 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1124 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1125 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1126 }
718e3744 1127 }
1128 }
1129 return 0;
1130}
1131
93406d87 1132void
1133peer_nsf_stop (struct peer *peer)
1134{
1135 afi_t afi;
1136 safi_t safi;
1137
1138 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1139 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1140
1141 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1142 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1143 peer->nsf[afi][safi] = 0;
1144
1145 if (peer->t_gr_restart)
1146 {
1147 BGP_TIMER_OFF (peer->t_gr_restart);
1148 if (BGP_DEBUG (events, EVENTS))
1149 zlog_debug ("%s graceful restart timer stopped", peer->host);
1150 }
1151 if (peer->t_gr_stale)
1152 {
1153 BGP_TIMER_OFF (peer->t_gr_stale);
1154 if (BGP_DEBUG (events, EVENTS))
1155 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1156 }
1157 bgp_clear_route_all (peer);
1158}
1159
ca058a30
PJ
1160/* Delete peer from confguration.
1161 *
1162 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1163 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1164 *
1165 * This function /should/ take care to be idempotent, to guard against
1166 * it being called multiple times through stray events that come in
1167 * that happen to result in this function being called again. That
1168 * said, getting here for a "Deleted" peer is a bug in the neighbour
1169 * FSM.
1170 */
718e3744 1171int
1172peer_delete (struct peer *peer)
1173{
1174 int i;
1175 afi_t afi;
1176 safi_t safi;
1177 struct bgp *bgp;
1178 struct bgp_filter *filter;
228da428 1179 struct listnode *pn;
718e3744 1180
ca058a30
PJ
1181 assert (peer->status != Deleted);
1182
718e3744 1183 bgp = peer->bgp;
1184
93406d87 1185 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1186 peer_nsf_stop (peer);
1187
228da428 1188 /* If this peer belongs to peer group, clear up the
718e3744 1189 relationship. */
1190 if (peer->group)
1191 {
ca058a30
PJ
1192 if ((pn = listnode_lookup (peer->group->peer, peer)))
1193 {
1194 peer = peer_unlock (peer); /* group->peer list reference */
1195 list_delete_node (peer->group->peer, pn);
1196 }
718e3744 1197 peer->group = NULL;
1198 }
200df115 1199
718e3744 1200 /* Withdraw all information from routing table. We can not use
200df115 1201 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1202 * executed after peer structure is deleted.
1203 */
e0701b79 1204 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
718e3744 1205 bgp_stop (peer);
ca058a30 1206 bgp_fsm_change_status (peer, Deleted);
0df7c91f
PJ
1207
1208 /* Password configuration */
1209 if (peer->password)
1210 {
1211 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1212 peer->password = NULL;
1213
1214 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1215 bgp_md5_set (peer);
1216 }
1217
ca058a30 1218 bgp_timer_set (peer); /* stops all timers for Deleted */
200df115 1219
718e3744 1220 /* Delete from all peer list. */
228da428
CC
1221 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1222 && (pn = listnode_lookup (bgp->peer, peer)))
fee0f4c6 1223 {
228da428
CC
1224 peer_unlock (peer); /* bgp peer list reference */
1225 list_delete_node (bgp->peer, pn);
1226 }
200df115 1227
228da428
CC
1228 if (peer_rsclient_active (peer)
1229 && (pn = listnode_lookup (bgp->rsclient, peer)))
1230 {
1231 peer_unlock (peer); /* rsclient list reference */
1232 list_delete_node (bgp->rsclient, pn);
1233
1234 /* Clear our own rsclient ribs. */
1235 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1236 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1237 if (CHECK_FLAG(peer->af_flags[afi][safi],
1238 PEER_FLAG_RSERVER_CLIENT))
1239 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
fee0f4c6 1240 }
1241
1242 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1243 member of a peer_group. */
1244 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1245 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1246 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
b608d5b5 1247 bgp_table_finish (&peer->rib[afi][safi]);
718e3744 1248
200df115 1249 /* Buffers. */
718e3744 1250 if (peer->ibuf)
1251 stream_free (peer->ibuf);
718e3744 1252 if (peer->obuf)
1253 stream_fifo_free (peer->obuf);
718e3744 1254 if (peer->work)
1255 stream_free (peer->work);
18937400
PJ
1256 peer->obuf = NULL;
1257 peer->work = peer->ibuf = NULL;
1258
718e3744 1259 /* Local and remote addresses. */
1260 if (peer->su_local)
22db9dec 1261 sockunion_free (peer->su_local);
718e3744 1262 if (peer->su_remote)
22db9dec 1263 sockunion_free (peer->su_remote);
18937400 1264 peer->su_local = peer->su_remote = NULL;
200df115 1265
718e3744 1266 /* Free filter related memory. */
1267 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1268 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1269 {
1270 filter = &peer->filter[afi][safi];
1271
1272 for (i = FILTER_IN; i < FILTER_MAX; i++)
1273 {
1274 if (filter->dlist[i].name)
1275 free (filter->dlist[i].name);
1276 if (filter->plist[i].name)
1277 free (filter->plist[i].name);
1278 if (filter->aslist[i].name)
1279 free (filter->aslist[i].name);
200df115 1280
1281 filter->dlist[i].name = NULL;
1282 filter->plist[i].name = NULL;
1283 filter->aslist[i].name = NULL;
1284 }
1285 for (i = RMAP_IN; i < RMAP_MAX; i++)
1286 {
718e3744 1287 if (filter->map[i].name)
1288 free (filter->map[i].name);
200df115 1289 filter->map[i].name = NULL;
718e3744 1290 }
1291
1292 if (filter->usmap.name)
1293 free (filter->usmap.name);
1294
1295 if (peer->default_rmap[afi][safi].name)
1296 free (peer->default_rmap[afi][safi].name);
200df115 1297
1298 filter->usmap.name = NULL;
1299 peer->default_rmap[afi][safi].name = NULL;
718e3744 1300 }
200df115 1301
1302 peer_unlock (peer); /* initial reference */
718e3744 1303
1304 return 0;
1305}
1306\f
94f2b392 1307static int
718e3744 1308peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1309{
1310 return strcmp (g1->name, g2->name);
1311}
1312
1313/* If peer is configured at least one address family return 1. */
94f2b392 1314static int
718e3744 1315peer_group_active (struct peer *peer)
1316{
1317 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1318 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1319 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1320 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1321 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1322 return 1;
1323 return 0;
1324}
1325
1326/* Peer group cofiguration. */
1327static struct peer_group *
66e5cd87 1328peer_group_new (void)
718e3744 1329{
1330 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1331 sizeof (struct peer_group));
1332}
1333
94f2b392 1334static void
718e3744 1335peer_group_free (struct peer_group *group)
1336{
1337 XFREE (MTYPE_PEER_GROUP, group);
1338}
1339
1340struct peer_group *
fd79ac91 1341peer_group_lookup (struct bgp *bgp, const char *name)
718e3744 1342{
1343 struct peer_group *group;
1eb8ef25 1344 struct listnode *node, *nnode;
718e3744 1345
1eb8ef25 1346 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 1347 {
1348 if (strcmp (group->name, name) == 0)
1349 return group;
1350 }
1351 return NULL;
1352}
1353
1354struct peer_group *
fd79ac91 1355peer_group_get (struct bgp *bgp, const char *name)
718e3744 1356{
1357 struct peer_group *group;
1358
1359 group = peer_group_lookup (bgp, name);
1360 if (group)
1361 return group;
1362
1363 group = peer_group_new ();
1364 group->bgp = bgp;
1365 group->name = strdup (name);
1366 group->peer = list_new ();
6f58544d 1367 group->conf = peer_new (bgp);
718e3744 1368 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1369 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
228da428 1370 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
718e3744 1371 group->conf->group = group;
1372 group->conf->as = 0;
1373 group->conf->ttl = 1;
1374 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1375 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1376 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1377 group->conf->keepalive = 0;
1378 group->conf->holdtime = 0;
1379 group->conf->connect = 0;
1380 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1381 listnode_add_sort (bgp->group, group);
1382
1383 return 0;
1384}
1385
94f2b392 1386static void
718e3744 1387peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1388 afi_t afi, safi_t safi)
1389{
1390 int in = FILTER_IN;
1391 int out = FILTER_OUT;
1392 struct peer *conf;
1393 struct bgp_filter *pfilter;
1394 struct bgp_filter *gfilter;
1395
1396 conf = group->conf;
1397 pfilter = &peer->filter[afi][safi];
1398 gfilter = &conf->filter[afi][safi];
1399
1400 /* remote-as */
1401 if (conf->as)
1402 peer->as = conf->as;
1403
1404 /* remote-as */
1405 if (conf->change_local_as)
1406 peer->change_local_as = conf->change_local_as;
1407
1408 /* TTL */
1409 peer->ttl = conf->ttl;
1410
1411 /* Weight */
1412 peer->weight = conf->weight;
1413
1414 /* peer flags apply */
1415 peer->flags = conf->flags;
1416 /* peer af_flags apply */
1417 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1418 /* peer config apply */
1419 peer->config = conf->config;
1420
1421 /* peer timers apply */
1422 peer->holdtime = conf->holdtime;
1423 peer->keepalive = conf->keepalive;
1424 peer->connect = conf->connect;
1425 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1426 peer->v_connect = conf->connect;
1427 else
1428 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1429
1430 /* advertisement-interval reset */
1431 if (peer_sort (peer) == BGP_PEER_IBGP)
1432 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1433 else
1434 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1435
0df7c91f
PJ
1436 /* password apply */
1437 if (peer->password)
1438 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1439
1440 if (conf->password)
1441 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1442 else
1443 peer->password = NULL;
1444
1445 bgp_md5_set (peer);
1446
718e3744 1447 /* maximum-prefix */
1448 peer->pmax[afi][safi] = conf->pmax[afi][safi];
e0701b79 1449 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
0a486e5f 1450 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
718e3744 1451
1452 /* allowas-in */
1453 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1454
fee0f4c6 1455 /* route-server-client */
1456 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1457 {
1458 /* Make peer's RIB point to group's RIB. */
1459 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1460
1461 /* Import policy. */
1462 if (pfilter->map[RMAP_IMPORT].name)
1463 free (pfilter->map[RMAP_IMPORT].name);
1464 if (gfilter->map[RMAP_IMPORT].name)
1465 {
1466 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1467 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1468 }
1469 else
1470 {
1471 pfilter->map[RMAP_IMPORT].name = NULL;
1472 pfilter->map[RMAP_IMPORT].map = NULL;
1473 }
1474
1475 /* Export policy. */
1476 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1477 {
1478 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1479 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1480 }
1481 }
1482
718e3744 1483 /* default-originate route-map */
1484 if (conf->default_rmap[afi][safi].name)
1485 {
1486 if (peer->default_rmap[afi][safi].name)
1487 free (peer->default_rmap[afi][safi].name);
1488 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1489 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1490 }
1491
1492 /* update-source apply */
1493 if (conf->update_source)
1494 {
1495 if (peer->update_source)
1496 sockunion_free (peer->update_source);
1497 if (peer->update_if)
1498 {
1499 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1500 peer->update_if = NULL;
1501 }
1502 peer->update_source = sockunion_dup (conf->update_source);
1503 }
1504 else if (conf->update_if)
1505 {
1506 if (peer->update_if)
1507 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1508 if (peer->update_source)
1509 {
1510 sockunion_free (peer->update_source);
1511 peer->update_source = NULL;
1512 }
1513 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1514 }
1515
1516 /* inbound filter apply */
1517 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1518 {
1519 if (pfilter->dlist[in].name)
1520 free (pfilter->dlist[in].name);
1521 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1522 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1523 }
1524 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1525 {
1526 if (pfilter->plist[in].name)
1527 free (pfilter->plist[in].name);
1528 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1529 pfilter->plist[in].plist = gfilter->plist[in].plist;
1530 }
1531 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1532 {
1533 if (pfilter->aslist[in].name)
1534 free (pfilter->aslist[in].name);
1535 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1536 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1537 }
fee0f4c6 1538 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
718e3744 1539 {
fee0f4c6 1540 if (pfilter->map[RMAP_IN].name)
1541 free (pfilter->map[RMAP_IN].name);
1542 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1543 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
718e3744 1544 }
1545
1546 /* outbound filter apply */
1547 if (gfilter->dlist[out].name)
1548 {
1549 if (pfilter->dlist[out].name)
1550 free (pfilter->dlist[out].name);
1551 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1552 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1553 }
1554 else
1555 {
1556 if (pfilter->dlist[out].name)
1557 free (pfilter->dlist[out].name);
1558 pfilter->dlist[out].name = NULL;
1559 pfilter->dlist[out].alist = NULL;
1560 }
1561 if (gfilter->plist[out].name)
1562 {
1563 if (pfilter->plist[out].name)
1564 free (pfilter->plist[out].name);
1565 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1566 pfilter->plist[out].plist = gfilter->plist[out].plist;
1567 }
1568 else
1569 {
1570 if (pfilter->plist[out].name)
1571 free (pfilter->plist[out].name);
1572 pfilter->plist[out].name = NULL;
1573 pfilter->plist[out].plist = NULL;
1574 }
1575 if (gfilter->aslist[out].name)
1576 {
1577 if (pfilter->aslist[out].name)
1578 free (pfilter->aslist[out].name);
1579 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1580 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1581 }
1582 else
1583 {
1584 if (pfilter->aslist[out].name)
1585 free (pfilter->aslist[out].name);
1586 pfilter->aslist[out].name = NULL;
1587 pfilter->aslist[out].aslist = NULL;
1588 }
fee0f4c6 1589 if (gfilter->map[RMAP_OUT].name)
1590 {
1591 if (pfilter->map[RMAP_OUT].name)
1592 free (pfilter->map[RMAP_OUT].name);
1593 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1594 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
1595 }
1596 else
1597 {
1598 if (pfilter->map[RMAP_OUT].name)
1599 free (pfilter->map[RMAP_OUT].name);
1600 pfilter->map[RMAP_OUT].name = NULL;
1601 pfilter->map[RMAP_OUT].map = NULL;
1602 }
1603
1604 /* RS-client's import/export route-maps. */
1605 if (gfilter->map[RMAP_IMPORT].name)
718e3744 1606 {
fee0f4c6 1607 if (pfilter->map[RMAP_IMPORT].name)
1608 free (pfilter->map[RMAP_IMPORT].name);
1609 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1610 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
718e3744 1611 }
1612 else
1613 {
fee0f4c6 1614 if (pfilter->map[RMAP_IMPORT].name)
1615 free (pfilter->map[RMAP_IMPORT].name);
1616 pfilter->map[RMAP_IMPORT].name = NULL;
1617 pfilter->map[RMAP_IMPORT].map = NULL;
1618 }
1619 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1620 {
1621 if (pfilter->map[RMAP_EXPORT].name)
1622 free (pfilter->map[RMAP_EXPORT].name);
1623 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1624 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
718e3744 1625 }
1626
1627 if (gfilter->usmap.name)
1628 {
1629 if (pfilter->usmap.name)
1630 free (pfilter->usmap.name);
1631 pfilter->usmap.name = strdup (gfilter->usmap.name);
1632 pfilter->usmap.map = gfilter->usmap.map;
1633 }
1634 else
1635 {
1636 if (pfilter->usmap.name)
1637 free (pfilter->usmap.name);
1638 pfilter->usmap.name = NULL;
1639 pfilter->usmap.map = NULL;
1640 }
1641}
1642
1643/* Peer group's remote AS configuration. */
1644int
fd79ac91 1645peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
718e3744 1646{
1647 struct peer_group *group;
1648 struct peer *peer;
1eb8ef25 1649 struct listnode *node, *nnode;
718e3744 1650
1651 group = peer_group_lookup (bgp, group_name);
1652 if (! group)
1653 return -1;
1654
1655 if (group->conf->as == *as)
1656 return 0;
1657
1658 /* When we setup peer-group AS number all peer group member's AS
1659 number must be updated to same number. */
1660 peer_as_change (group->conf, *as);
1661
1eb8ef25 1662 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 1663 {
1664 if (peer->as != *as)
1665 peer_as_change (peer, *as);
1666 }
1667
1668 return 0;
1669}
1670
1671int
1672peer_group_delete (struct peer_group *group)
1673{
1674 struct bgp *bgp;
1675 struct peer *peer;
1eb8ef25 1676 struct listnode *node, *nnode;
718e3744 1677
1678 bgp = group->bgp;
1679
1eb8ef25 1680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 1681 {
1682 peer->group = NULL;
1683 peer_delete (peer);
1684 }
1685 list_delete (group->peer);
1686
1687 free (group->name);
1688 group->name = NULL;
1689
1690 group->conf->group = NULL;
1691 peer_delete (group->conf);
1692
1693 /* Delete from all peer_group list. */
1694 listnode_delete (bgp->group, group);
1695
1696 peer_group_free (group);
1697
1698 return 0;
1699}
1700
1701int
1702peer_group_remote_as_delete (struct peer_group *group)
1703{
1704 struct peer *peer;
1eb8ef25 1705 struct listnode *node, *nnode;
718e3744 1706
1707 if (! group->conf->as)
1708 return 0;
1709
1eb8ef25 1710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 1711 {
1712 peer->group = NULL;
1713 peer_delete (peer);
1714 }
1715 list_delete_all_node (group->peer);
1716
1717 group->conf->as = 0;
1718
1719 return 0;
1720}
1721
1722/* Bind specified peer to peer group. */
1723int
1724peer_group_bind (struct bgp *bgp, union sockunion *su,
1725 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1726{
1727 struct peer *peer;
1728 int first_member = 0;
1729
1730 /* Check peer group's address family. */
1731 if (! group->conf->afc[afi][safi])
1732 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1733
1734 /* Lookup the peer. */
1735 peer = peer_lookup (bgp, su);
1736
1737 /* Create a new peer. */
1738 if (! peer)
1739 {
1740 if (! group->conf->as)
1741 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1742
1743 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1744 peer->group = group;
1745 peer->af_group[afi][safi] = 1;
200df115 1746
ca058a30 1747 peer = peer_lock (peer); /* group->peer list reference */
718e3744 1748 listnode_add (group->peer, peer);
1749 peer_group2peer_config_copy (group, peer, afi, safi);
1750
1751 return 0;
1752 }
1753
1754 /* When the peer already belongs to peer group, check the consistency. */
1755 if (peer->af_group[afi][safi])
1756 {
1757 if (strcmp (peer->group->name, group->name) != 0)
1758 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1759
1760 return 0;
1761 }
1762
1763 /* Check current peer group configuration. */
1764 if (peer_group_active (peer)
1765 && strcmp (peer->group->name, group->name) != 0)
1766 return BGP_ERR_PEER_GROUP_MISMATCH;
1767
1768 if (! group->conf->as)
1769 {
1770 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1771 && peer_sort (group->conf) != peer_sort (peer))
1772 {
1773 if (as)
1774 *as = peer->as;
1775 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1776 }
1777
1778 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1779 first_member = 1;
1780 }
1781
1782 peer->af_group[afi][safi] = 1;
1783 peer->afc[afi][safi] = 1;
1784 if (! peer->group)
1785 {
1786 peer->group = group;
200df115 1787
ca058a30 1788 peer = peer_lock (peer); /* group->peer list reference */
718e3744 1789 listnode_add (group->peer, peer);
1790 }
ca058a30
PJ
1791 else
1792 assert (group && peer->group == group);
718e3744 1793
1794 if (first_member)
1795 {
1796 /* Advertisement-interval reset */
1797 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1798 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1799 else
1800 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1801
1802 /* ebgp-multihop reset */
1803 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1804 group->conf->ttl = 255;
1805
1806 /* local-as reset */
1807 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1808 {
1809 group->conf->change_local_as = 0;
1810 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1811 }
1812 }
fee0f4c6 1813
1814 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1815 {
ca058a30
PJ
1816 struct listnode *pn;
1817
fee0f4c6 1818 /* If it's not configured as RSERVER_CLIENT in any other address
1819 family, without being member of a peer_group, remove it from
1820 list bgp->rsclient.*/
ca058a30
PJ
1821 if (! peer_rsclient_active (peer)
1822 && (pn = listnode_lookup (bgp->rsclient, peer)))
200df115 1823 {
1824 peer_unlock (peer); /* peer rsclient reference */
ca058a30 1825 list_delete_node (bgp->rsclient, pn);
228da428
CC
1826
1827 /* Clear our own rsclient rib for this afi/safi. */
1828 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
200df115 1829 }
fee0f4c6 1830
b608d5b5 1831 bgp_table_finish (&peer->rib[afi][safi]);
fee0f4c6 1832
1833 /* Import policy. */
1834 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1835 {
1836 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1837 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1838 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1839 }
1840
1841 /* Export policy. */
1842 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1843 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1844 {
1845 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1846 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1847 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1848 }
1849 }
1850
718e3744 1851 peer_group2peer_config_copy (group, peer, afi, safi);
1852
1853 if (peer->status == Established)
e0701b79 1854 {
1855 peer->last_reset = PEER_DOWN_RMAP_BIND;
1856 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1857 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1858 }
718e3744 1859 else
1860 BGP_EVENT_ADD (peer, BGP_Stop);
1861
1862 return 0;
1863}
1864
1865int
1866peer_group_unbind (struct bgp *bgp, struct peer *peer,
1867 struct peer_group *group, afi_t afi, safi_t safi)
1868{
1869 if (! peer->af_group[afi][safi])
1870 return 0;
1871
1872 if (group != peer->group)
1873 return BGP_ERR_PEER_GROUP_MISMATCH;
1874
1875 peer->af_group[afi][safi] = 0;
1876 peer->afc[afi][safi] = 0;
1877 peer_af_flag_reset (peer, afi, safi);
1878
fee0f4c6 1879 if (peer->rib[afi][safi])
1880 peer->rib[afi][safi] = NULL;
1881
718e3744 1882 if (! peer_group_active (peer))
1883 {
ca058a30 1884 assert (listnode_lookup (group->peer, peer));
200df115 1885 peer_unlock (peer); /* peer group list reference */
718e3744 1886 listnode_delete (group->peer, peer);
1887 peer->group = NULL;
1888 if (group->conf->as)
1889 {
1890 peer_delete (peer);
1891 return 0;
1892 }
1893 peer_global_config_reset (peer);
1894 }
1895
1896 if (peer->status == Established)
e0701b79 1897 {
1898 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1901 }
718e3744 1902 else
1903 BGP_EVENT_ADD (peer, BGP_Stop);
1904
1905 return 0;
1906}
1907\f
1908/* BGP instance creation by `router bgp' commands. */
94f2b392 1909static struct bgp *
fd79ac91 1910bgp_create (as_t *as, const char *name)
718e3744 1911{
1912 struct bgp *bgp;
1913 afi_t afi;
1914 safi_t safi;
1915
200df115 1916 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1917 return NULL;
1918
0088b5dc 1919 bgp_lock (bgp);
6f58544d 1920 bgp->peer_self = peer_new (bgp);
228da428 1921 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
718e3744 1922
1923 bgp->peer = list_new ();
1924 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1925
1926 bgp->group = list_new ();
1927 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1928
fee0f4c6 1929 bgp->rsclient = list_new ();
1930 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1931
718e3744 1932 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1933 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1934 {
64e580a7
PJ
1935 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1936 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1937 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
718e3744 1938 }
1939
1940 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1941 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1942 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
538621f2 1943 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1944 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
718e3744 1945
1946 bgp->as = *as;
1947
1948 if (name)
1949 bgp->name = strdup (name);
1950
1951 return bgp;
1952}
1953
1954/* Return first entry of BGP. */
1955struct bgp *
94f2b392 1956bgp_get_default (void)
718e3744 1957{
1958 if (bm->bgp->head)
1eb8ef25 1959 return (listgetdata (listhead (bm->bgp)));
718e3744 1960 return NULL;
1961}
1962
1963/* Lookup BGP entry. */
1964struct bgp *
fd79ac91 1965bgp_lookup (as_t as, const char *name)
718e3744 1966{
1967 struct bgp *bgp;
1eb8ef25 1968 struct listnode *node, *nnode;
718e3744 1969
1eb8ef25 1970 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 1971 if (bgp->as == as
1972 && ((bgp->name == NULL && name == NULL)
1973 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1974 return bgp;
1975 return NULL;
1976}
1977
1978/* Lookup BGP structure by view name. */
1979struct bgp *
fd79ac91 1980bgp_lookup_by_name (const char *name)
718e3744 1981{
1982 struct bgp *bgp;
1eb8ef25 1983 struct listnode *node, *nnode;
718e3744 1984
1eb8ef25 1985 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 1986 if ((bgp->name == NULL && name == NULL)
1987 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1988 return bgp;
1989 return NULL;
1990}
1991
1992/* Called from VTY commands. */
1993int
fd79ac91 1994bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
718e3744 1995{
1996 struct bgp *bgp;
1997
1998 /* Multiple instance check. */
1999 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2000 {
2001 if (name)
2002 bgp = bgp_lookup_by_name (name);
2003 else
2004 bgp = bgp_get_default ();
2005
2006 /* Already exists. */
2007 if (bgp)
2008 {
2009 if (bgp->as != *as)
2010 {
2011 *as = bgp->as;
2012 return BGP_ERR_INSTANCE_MISMATCH;
2013 }
2014 *bgp_val = bgp;
2015 return 0;
2016 }
2017 }
2018 else
2019 {
2020 /* BGP instance name can not be specified for single instance. */
2021 if (name)
2022 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2023
2024 /* Get default BGP structure if exists. */
2025 bgp = bgp_get_default ();
2026
2027 if (bgp)
2028 {
2029 if (bgp->as != *as)
2030 {
2031 *as = bgp->as;
2032 return BGP_ERR_AS_MISMATCH;
2033 }
2034 *bgp_val = bgp;
2035 return 0;
2036 }
2037 }
2038
2039 bgp = bgp_create (as, name);
2040 listnode_add (bm->bgp, bgp);
18a6dce6 2041 bgp_router_id_set(bgp, &router_id_zebra);
718e3744 2042 *bgp_val = bgp;
2043
2044 return 0;
2045}
2046
2047/* Delete BGP instance. */
2048int
2049bgp_delete (struct bgp *bgp)
2050{
2051 struct peer *peer;
b6b7cff2 2052 struct peer_group *group;
1eb8ef25 2053 struct listnode *node;
718e3744 2054 struct listnode *next;
2055 afi_t afi;
718e3744 2056 int i;
2057
2058 /* Delete static route. */
2059 bgp_static_delete (bgp);
2060
2061 /* Unset redistribution. */
2062 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2063 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2064 if (i != ZEBRA_ROUTE_BGP)
2065 bgp_redistribute_unset (bgp, afi, i);
2066
1eb8ef25 2067 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2068 peer_delete (peer);
718e3744 2069
228da428
CC
2070 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2071 peer_group_delete (group);
2072
2073 assert (listcount (bgp->rsclient) == 0);
0088b5dc
SH
2074
2075 if (bgp->peer_self) {
2076 peer_delete(bgp->peer_self);
2077 bgp->peer_self = NULL;
2078 }
fd35b948
PJ
2079
2080 /* Remove visibility via the master list - there may however still be
2081 * routes to be processed still referencing the struct bgp.
2082 */
2083 listnode_delete (bm->bgp, bgp);
2084
0088b5dc 2085 bgp_unlock(bgp); /* initial reference */
fd35b948 2086
0088b5dc
SH
2087 return 0;
2088}
2089
2090static void bgp_free (struct bgp *);
2091
2092void
2093bgp_lock (struct bgp *bgp)
2094{
2095 ++bgp->lock;
2096}
2097
2098void
2099bgp_unlock(struct bgp *bgp)
2100{
228da428 2101 assert(bgp->lock > 0);
0088b5dc
SH
2102 if (--bgp->lock == 0)
2103 bgp_free (bgp);
2104}
2105
2106static void
2107bgp_free (struct bgp *bgp)
2108{
2109 afi_t afi;
2110 safi_t safi;
2111
2112 list_delete (bgp->group);
2113 list_delete (bgp->peer);
fee0f4c6 2114 list_delete (bgp->rsclient);
2115
718e3744 2116 if (bgp->name)
2117 free (bgp->name);
2118
2119 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2120 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2121 {
2122 if (bgp->route[afi][safi])
228da428 2123 bgp_table_finish (&bgp->route[afi][safi]);
718e3744 2124 if (bgp->aggregate[afi][safi])
228da428 2125 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
718e3744 2126 if (bgp->rib[afi][safi])
228da428 2127 bgp_table_finish (&bgp->rib[afi][safi]);
718e3744 2128 }
2129 XFREE (MTYPE_BGP, bgp);
718e3744 2130}
2131\f
2132struct peer *
2133peer_lookup (struct bgp *bgp, union sockunion *su)
2134{
2135 struct peer *peer;
1eb8ef25 2136 struct listnode *node, *nnode;
718e3744 2137
2138 if (! bgp)
2139 bgp = bgp_get_default ();
2140
2141 if (! bgp)
2142 return NULL;
2143
1eb8ef25 2144 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 2145 {
eb821189 2146 if (sockunion_same (&peer->su, su)
2147 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2148 return peer;
718e3744 2149 }
2150 return NULL;
2151}
2152
2153struct peer *
2154peer_lookup_with_open (union sockunion *su, as_t remote_as,
2155 struct in_addr *remote_id, int *as)
2156{
2157 struct peer *peer;
1eb8ef25 2158 struct listnode *node, *nnode;
718e3744 2159 struct bgp *bgp;
2160
2161 bgp = bgp_get_default ();
2162 if (! bgp)
2163 return NULL;
2164
1eb8ef25 2165 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 2166 {
eb821189 2167 if (sockunion_same (&peer->su, su)
2168 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2169 {
2170 if (peer->as == remote_as
2171 && peer->remote_id.s_addr == remote_id->s_addr)
2172 return peer;
2173 if (peer->as == remote_as)
2174 *as = 1;
2175 }
718e3744 2176 }
1eb8ef25 2177 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 2178 {
eb821189 2179 if (sockunion_same (&peer->su, su)
2180 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2181 {
2182 if (peer->as == remote_as
2183 && peer->remote_id.s_addr == 0)
2184 return peer;
2185 if (peer->as == remote_as)
2186 *as = 1;
2187 }
718e3744 2188 }
2189 return NULL;
2190}
2191\f
2192/* If peer is configured at least one address family return 1. */
2193int
2194peer_active (struct peer *peer)
2195{
2196 if (peer->afc[AFI_IP][SAFI_UNICAST]
2197 || peer->afc[AFI_IP][SAFI_MULTICAST]
2198 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2199 || peer->afc[AFI_IP6][SAFI_UNICAST]
2200 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2201 return 1;
2202 return 0;
2203}
2204
2205/* If peer is negotiated at least one address family return 1. */
2206int
2207peer_active_nego (struct peer *peer)
2208{
2209 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2210 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2211 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2212 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2213 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2214 return 1;
2215 return 0;
2216}
2217\f
2218/* peer_flag_change_type. */
2219enum peer_change_type
2220{
2221 peer_change_none,
2222 peer_change_reset,
2223 peer_change_reset_in,
2224 peer_change_reset_out,
2225};
2226
94f2b392 2227static void
718e3744 2228peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2229 enum peer_change_type type)
2230{
2231 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2232 return;
2233
2234 if (type == peer_change_reset)
2235 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2236 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2237 else if (type == peer_change_reset_in)
2238 {
2239 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2240 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2241 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2242 else
2243 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2244 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2245 }
2246 else if (type == peer_change_reset_out)
2247 bgp_announce_route (peer, afi, safi);
2248}
2249
2250struct peer_flag_action
2251{
2252 /* Peer's flag. */
2253 u_int32_t flag;
2254
2255 /* This flag can be set for peer-group member. */
2256 u_char not_for_member;
2257
2258 /* Action when the flag is changed. */
2259 enum peer_change_type type;
e0701b79 2260
2261 /* Peer down cause */
2262 u_char peer_down;
718e3744 2263};
2264
2265struct peer_flag_action peer_flag_action_list[] =
2266 {
2267 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2268 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2269 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2270 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2271 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
718e3744 2272 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
6ffd2079 2273 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
718e3744 2274 { 0, 0, 0 }
2275 };
2276
2277struct peer_flag_action peer_af_flag_action_list[] =
2278 {
2279 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2280 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2281 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2282 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2283 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2284 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2285 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2286 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2287 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2288 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2289 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2290 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2291 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
fee0f4c6 2292 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
718e3744 2293 { 0, 0, 0 }
2294 };
2295
2296/* Proper action set. */
94f2b392 2297static int
718e3744 2298peer_flag_action_set (struct peer_flag_action *action_list, int size,
2299 struct peer_flag_action *action, u_int32_t flag)
2300{
2301 int i;
2302 int found = 0;
2303 int reset_in = 0;
2304 int reset_out = 0;
2305 struct peer_flag_action *match = NULL;
2306
2307 /* Check peer's frag action. */
2308 for (i = 0; i < size; i++)
2309 {
2310 match = &action_list[i];
2311
2312 if (match->flag == 0)
2313 break;
2314
2315 if (match->flag & flag)
2316 {
2317 found = 1;
2318
2319 if (match->type == peer_change_reset_in)
2320 reset_in = 1;
2321 if (match->type == peer_change_reset_out)
2322 reset_out = 1;
2323 if (match->type == peer_change_reset)
2324 {
2325 reset_in = 1;
2326 reset_out = 1;
2327 }
2328 if (match->not_for_member)
2329 action->not_for_member = 1;
2330 }
2331 }
2332
2333 /* Set peer clear type. */
2334 if (reset_in && reset_out)
2335 action->type = peer_change_reset;
2336 else if (reset_in)
2337 action->type = peer_change_reset_in;
2338 else if (reset_out)
2339 action->type = peer_change_reset_out;
2340 else
2341 action->type = peer_change_none;
2342
2343 return found;
2344}
2345
94f2b392 2346static void
718e3744 2347peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2348{
2349 if (flag == PEER_FLAG_SHUTDOWN)
2350 {
2351 if (CHECK_FLAG (peer->flags, flag))
2352 {
93406d87 2353 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2354 peer_nsf_stop (peer);
2355
0a486e5f 2356 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2357 if (peer->t_pmax_restart)
2358 {
2359 BGP_TIMER_OFF (peer->t_pmax_restart);
2360 if (BGP_DEBUG (events, EVENTS))
2361 zlog_debug ("%s Maximum-prefix restart timer canceled",
2362 peer->host);
2363 }
2364
93406d87 2365 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2366 peer_nsf_stop (peer);
2367
718e3744 2368 if (peer->status == Established)
2369 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2370 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2371 else
2372 BGP_EVENT_ADD (peer, BGP_Stop);
2373 }
2374 else
2375 {
2376 peer->v_start = BGP_INIT_START_TIMER;
2377 BGP_EVENT_ADD (peer, BGP_Stop);
2378 }
2379 }
2380 else if (peer->status == Established)
2381 {
c9502438 2382 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2383 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2384 else if (flag == PEER_FLAG_PASSIVE)
2385 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
6ffd2079 2386 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
c9502438 2387 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
e0701b79 2388
c9502438 2389 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2390 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
718e3744 2391 }
2392 else
2393 BGP_EVENT_ADD (peer, BGP_Stop);
2394}
2395
2396/* Change specified peer flag. */
94f2b392 2397static int
718e3744 2398peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2399{
2400 int found;
2401 int size;
2402 struct peer_group *group;
1eb8ef25 2403 struct listnode *node, *nnode;
718e3744 2404 struct peer_flag_action action;
2405
2406 memset (&action, 0, sizeof (struct peer_flag_action));
2407 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2408
2409 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2410
2411 /* No flag action is found. */
2412 if (! found)
2413 return BGP_ERR_INVALID_FLAG;
2414
2415 /* Not for peer-group member. */
2416 if (action.not_for_member && peer_group_active (peer))
2417 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2418
2419 /* When unset the peer-group member's flag we have to check
2420 peer-group configuration. */
2421 if (! set && peer_group_active (peer))
2422 if (CHECK_FLAG (peer->group->conf->flags, flag))
2423 {
2424 if (flag == PEER_FLAG_SHUTDOWN)
2425 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2426 else
2427 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2428 }
2429
2430 /* Flag conflict check. */
2431 if (set
2432 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2433 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2434 return BGP_ERR_PEER_FLAG_CONFLICT;
2435
2436 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2437 {
2438 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2439 return 0;
2440 if (! set && ! CHECK_FLAG (peer->flags, flag))
2441 return 0;
2442 }
2443
2444 if (set)
2445 SET_FLAG (peer->flags, flag);
2446 else
2447 UNSET_FLAG (peer->flags, flag);
2448
2449 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2450 {
2451 if (action.type == peer_change_reset)
2452 peer_flag_modify_action (peer, flag);
2453
2454 return 0;
2455 }
2456
2457 /* peer-group member updates. */
2458 group = peer->group;
2459
1eb8ef25 2460 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2461 {
2462 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2463 continue;
2464
2465 if (! set && ! CHECK_FLAG (peer->flags, flag))
2466 continue;
2467
2468 if (set)
2469 SET_FLAG (peer->flags, flag);
2470 else
2471 UNSET_FLAG (peer->flags, flag);
2472
2473 if (action.type == peer_change_reset)
2474 peer_flag_modify_action (peer, flag);
2475 }
2476 return 0;
2477}
2478
2479int
2480peer_flag_set (struct peer *peer, u_int32_t flag)
2481{
2482 return peer_flag_modify (peer, flag, 1);
2483}
2484
2485int
2486peer_flag_unset (struct peer *peer, u_int32_t flag)
2487{
2488 return peer_flag_modify (peer, flag, 0);
2489}
2490
94f2b392 2491static int
718e3744 2492peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2493{
2494 if (peer->af_group[afi][safi])
2495 return 1;
2496 return 0;
2497}
2498
94f2b392 2499static int
718e3744 2500peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2501 int set)
2502{
2503 int found;
2504 int size;
1eb8ef25 2505 struct listnode *node, *nnode;
718e3744 2506 struct peer_group *group;
2507 struct peer_flag_action action;
2508
2509 memset (&action, 0, sizeof (struct peer_flag_action));
2510 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2511
2512 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2513
2514 /* No flag action is found. */
2515 if (! found)
2516 return BGP_ERR_INVALID_FLAG;
2517
2518 /* Adress family must be activated. */
2519 if (! peer->afc[afi][safi])
2520 return BGP_ERR_PEER_INACTIVE;
2521
2522 /* Not for peer-group member. */
2523 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2524 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2525
2526 /* Spcecial check for reflector client. */
2527 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2528 && peer_sort (peer) != BGP_PEER_IBGP)
2529 return BGP_ERR_NOT_INTERNAL_PEER;
2530
2531 /* Spcecial check for remove-private-AS. */
2532 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2533 && peer_sort (peer) == BGP_PEER_IBGP)
2534 return BGP_ERR_REMOVE_PRIVATE_AS;
2535
2536 /* When unset the peer-group member's flag we have to check
2537 peer-group configuration. */
2538 if (! set && peer->af_group[afi][safi])
2539 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2540 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2541
2542 /* When current flag configuration is same as requested one. */
2543 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2544 {
2545 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2546 return 0;
2547 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2548 return 0;
2549 }
2550
2551 if (set)
2552 SET_FLAG (peer->af_flags[afi][safi], flag);
2553 else
2554 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2555
2556 /* Execute action when peer is established. */
2557 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2558 && peer->status == Established)
2559 {
2560 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2561 bgp_clear_adj_in (peer, afi, safi);
2562 else
e0701b79 2563 {
2564 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2565 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2566 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2567 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2568 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2569 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2570 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2571 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2572
2573 peer_change_action (peer, afi, safi, action.type);
2574 }
2575
718e3744 2576 }
2577
2578 /* Peer group member updates. */
2579 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2580 {
2581 group = peer->group;
2582
1eb8ef25 2583 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2584 {
2585 if (! peer->af_group[afi][safi])
2586 continue;
2587
2588 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2589 continue;
2590
2591 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2592 continue;
2593
2594 if (set)
2595 SET_FLAG (peer->af_flags[afi][safi], flag);
2596 else
2597 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2598
2599 if (peer->status == Established)
2600 {
2601 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2602 bgp_clear_adj_in (peer, afi, safi);
2603 else
e0701b79 2604 {
2605 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2606 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2607 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2608 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2609 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2610 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2611 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2612 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2613
2614 peer_change_action (peer, afi, safi, action.type);
2615 }
718e3744 2616 }
2617 }
2618 }
2619 return 0;
2620}
2621
2622int
2623peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2624{
2625 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2626}
2627
2628int
2629peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2630{
2631 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2632}
2633\f
2634/* EBGP multihop configuration. */
2635int
2636peer_ebgp_multihop_set (struct peer *peer, int ttl)
2637{
2638 struct peer_group *group;
1eb8ef25 2639 struct listnode *node, *nnode;
718e3744 2640
2641 if (peer_sort (peer) == BGP_PEER_IBGP)
2642 return 0;
2643
2644 peer->ttl = ttl;
2645
2646 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2647 {
eb821189 2648 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2649 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
718e3744 2650 }
2651 else
2652 {
2653 group = peer->group;
1eb8ef25 2654 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 2655 {
2656 if (peer_sort (peer) == BGP_PEER_IBGP)
2657 continue;
718e3744 2658
eb821189 2659 peer->ttl = group->conf->ttl;
718e3744 2660
eb821189 2661 if (peer->fd >= 0)
2662 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2663 }
718e3744 2664 }
2665 return 0;
2666}
2667
2668int
2669peer_ebgp_multihop_unset (struct peer *peer)
2670{
2671 struct peer_group *group;
1eb8ef25 2672 struct listnode *node, *nnode;
718e3744 2673
2674 if (peer_sort (peer) == BGP_PEER_IBGP)
2675 return 0;
2676
2677 if (peer_group_active (peer))
2678 peer->ttl = peer->group->conf->ttl;
2679 else
2680 peer->ttl = 1;
2681
2682 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2683 {
eb821189 2684 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2685 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
718e3744 2686 }
2687 else
2688 {
2689 group = peer->group;
1eb8ef25 2690 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 2691 {
2692 if (peer_sort (peer) == BGP_PEER_IBGP)
2693 continue;
2694
2695 peer->ttl = 1;
2696
2697 if (peer->fd >= 0)
2698 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2699 }
718e3744 2700 }
2701 return 0;
2702}
2703\f
2704/* Neighbor description. */
2705int
2706peer_description_set (struct peer *peer, char *desc)
2707{
2708 if (peer->desc)
2709 XFREE (MTYPE_PEER_DESC, peer->desc);
2710
2711 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2712
2713 return 0;
2714}
2715
2716int
2717peer_description_unset (struct peer *peer)
2718{
2719 if (peer->desc)
2720 XFREE (MTYPE_PEER_DESC, peer->desc);
2721
2722 peer->desc = NULL;
2723
2724 return 0;
2725}
2726\f
2727/* Neighbor update-source. */
2728int
fd79ac91 2729peer_update_source_if_set (struct peer *peer, const char *ifname)
718e3744 2730{
2731 struct peer_group *group;
1eb8ef25 2732 struct listnode *node, *nnode;
718e3744 2733
2734 if (peer->update_if)
2735 {
2736 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2737 && strcmp (peer->update_if, ifname) == 0)
2738 return 0;
2739
2740 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2741 peer->update_if = NULL;
2742 }
2743
2744 if (peer->update_source)
2745 {
2746 sockunion_free (peer->update_source);
2747 peer->update_source = NULL;
2748 }
2749
2750 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2751
2752 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2753 {
2754 if (peer->status == Established)
e0701b79 2755 {
2756 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2757 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2758 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2759 }
718e3744 2760 else
2761 BGP_EVENT_ADD (peer, BGP_Stop);
2762 return 0;
2763 }
2764
2765 /* peer-group member updates. */
2766 group = peer->group;
1eb8ef25 2767 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2768 {
2769 if (peer->update_if)
2770 {
2771 if (strcmp (peer->update_if, ifname) == 0)
2772 continue;
2773
2774 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2775 peer->update_if = NULL;
2776 }
2777
2778 if (peer->update_source)
2779 {
2780 sockunion_free (peer->update_source);
2781 peer->update_source = NULL;
2782 }
2783
2784 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2785
2786 if (peer->status == Established)
e0701b79 2787 {
2788 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2789 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2790 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2791 }
718e3744 2792 else
2793 BGP_EVENT_ADD (peer, BGP_Stop);
2794 }
2795 return 0;
2796}
2797
2798int
2799peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2800{
2801 struct peer_group *group;
1eb8ef25 2802 struct listnode *node, *nnode;
718e3744 2803
2804 if (peer->update_source)
2805 {
2806 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2807 && sockunion_cmp (peer->update_source, su) == 0)
2808 return 0;
2809 sockunion_free (peer->update_source);
2810 peer->update_source = NULL;
2811 }
2812
2813 if (peer->update_if)
2814 {
2815 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2816 peer->update_if = NULL;
2817 }
2818
2819 peer->update_source = sockunion_dup (su);
2820
2821 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2822 {
2823 if (peer->status == Established)
e0701b79 2824 {
2825 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2826 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2827 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2828 }
718e3744 2829 else
2830 BGP_EVENT_ADD (peer, BGP_Stop);
2831 return 0;
2832 }
2833
2834 /* peer-group member updates. */
2835 group = peer->group;
1eb8ef25 2836 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2837 {
2838 if (peer->update_source)
2839 {
2840 if (sockunion_cmp (peer->update_source, su) == 0)
2841 continue;
2842 sockunion_free (peer->update_source);
2843 peer->update_source = NULL;
2844 }
2845
2846 if (peer->update_if)
2847 {
2848 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2849 peer->update_if = NULL;
2850 }
2851
2852 peer->update_source = sockunion_dup (su);
2853
2854 if (peer->status == Established)
e0701b79 2855 {
2856 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2857 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2858 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2859 }
718e3744 2860 else
2861 BGP_EVENT_ADD (peer, BGP_Stop);
2862 }
2863 return 0;
2864}
2865
2866int
2867peer_update_source_unset (struct peer *peer)
2868{
2869 union sockunion *su;
2870 struct peer_group *group;
1eb8ef25 2871 struct listnode *node, *nnode;
718e3744 2872
2873 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2874 && ! peer->update_source
2875 && ! peer->update_if)
2876 return 0;
2877
2878 if (peer->update_source)
2879 {
2880 sockunion_free (peer->update_source);
2881 peer->update_source = NULL;
2882 }
2883 if (peer->update_if)
2884 {
2885 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2886 peer->update_if = NULL;
2887 }
2888
2889 if (peer_group_active (peer))
2890 {
2891 group = peer->group;
2892
2893 if (group->conf->update_source)
2894 {
2895 su = sockunion_dup (group->conf->update_source);
2896 peer->update_source = su;
2897 }
2898 else if (group->conf->update_if)
2899 peer->update_if =
2900 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2901 }
2902
2903 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2904 {
2905 if (peer->status == Established)
e0701b79 2906 {
2907 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2908 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2909 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2910 }
718e3744 2911 else
2912 BGP_EVENT_ADD (peer, BGP_Stop);
2913 return 0;
2914 }
2915
2916 /* peer-group member updates. */
2917 group = peer->group;
1eb8ef25 2918 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2919 {
2920 if (! peer->update_source && ! peer->update_if)
2921 continue;
2922
2923 if (peer->update_source)
2924 {
2925 sockunion_free (peer->update_source);
2926 peer->update_source = NULL;
2927 }
2928
2929 if (peer->update_if)
2930 {
2931 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2932 peer->update_if = NULL;
2933 }
2934
2935 if (peer->status == Established)
e0701b79 2936 {
2937 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2938 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2939 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2940 }
718e3744 2941 else
2942 BGP_EVENT_ADD (peer, BGP_Stop);
2943 }
2944 return 0;
2945}
2946\f
2947int
2948peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
fd79ac91 2949 const char *rmap)
718e3744 2950{
2951 struct peer_group *group;
1eb8ef25 2952 struct listnode *node, *nnode;
718e3744 2953
2954 /* Adress family must be activated. */
2955 if (! peer->afc[afi][safi])
2956 return BGP_ERR_PEER_INACTIVE;
2957
2958 /* Default originate can't be used for peer group memeber. */
2959 if (peer_is_group_member (peer, afi, safi))
2960 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2961
2962 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2963 || (rmap && ! peer->default_rmap[afi][safi].name)
2964 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2965 {
2966 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2967
2968 if (rmap)
2969 {
2970 if (peer->default_rmap[afi][safi].name)
2971 free (peer->default_rmap[afi][safi].name);
2972 peer->default_rmap[afi][safi].name = strdup (rmap);
2973 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2974 }
2975 }
2976
2977 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2978 {
2979 if (peer->status == Established && peer->afc_nego[afi][safi])
2980 bgp_default_originate (peer, afi, safi, 0);
2981 return 0;
2982 }
2983
2984 /* peer-group member updates. */
2985 group = peer->group;
1eb8ef25 2986 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2987 {
2988 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2989
2990 if (rmap)
2991 {
2992 if (peer->default_rmap[afi][safi].name)
2993 free (peer->default_rmap[afi][safi].name);
2994 peer->default_rmap[afi][safi].name = strdup (rmap);
2995 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2996 }
2997
2998 if (peer->status == Established && peer->afc_nego[afi][safi])
2999 bgp_default_originate (peer, afi, safi, 0);
3000 }
3001 return 0;
3002}
3003
3004int
3005peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3006{
3007 struct peer_group *group;
1eb8ef25 3008 struct listnode *node, *nnode;
718e3744 3009
3010 /* Adress family must be activated. */
3011 if (! peer->afc[afi][safi])
3012 return BGP_ERR_PEER_INACTIVE;
3013
3014 /* Default originate can't be used for peer group memeber. */
3015 if (peer_is_group_member (peer, afi, safi))
3016 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3017
3018 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3019 {
3020 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3021
3022 if (peer->default_rmap[afi][safi].name)
3023 free (peer->default_rmap[afi][safi].name);
3024 peer->default_rmap[afi][safi].name = NULL;
3025 peer->default_rmap[afi][safi].map = NULL;
3026 }
3027
3028 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3029 {
3030 if (peer->status == Established && peer->afc_nego[afi][safi])
3031 bgp_default_originate (peer, afi, safi, 1);
3032 return 0;
3033 }
3034
3035 /* peer-group member updates. */
3036 group = peer->group;
1eb8ef25 3037 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3038 {
3039 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3040
3041 if (peer->default_rmap[afi][safi].name)
3042 free (peer->default_rmap[afi][safi].name);
3043 peer->default_rmap[afi][safi].name = NULL;
3044 peer->default_rmap[afi][safi].map = NULL;
3045
3046 if (peer->status == Established && peer->afc_nego[afi][safi])
3047 bgp_default_originate (peer, afi, safi, 1);
3048 }
3049 return 0;
3050}
3051\f
3052int
3053peer_port_set (struct peer *peer, u_int16_t port)
3054{
3055 peer->port = port;
3056 return 0;
3057}
3058
3059int
3060peer_port_unset (struct peer *peer)
3061{
3062 peer->port = BGP_PORT_DEFAULT;
3063 return 0;
3064}
3065\f
3066/* neighbor weight. */
3067int
3068peer_weight_set (struct peer *peer, u_int16_t weight)
3069{
3070 struct peer_group *group;
1eb8ef25 3071 struct listnode *node, *nnode;
718e3744 3072
3073 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3074 peer->weight = weight;
3075
3076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3077 return 0;
3078
3079 /* peer-group member updates. */
3080 group = peer->group;
1eb8ef25 3081 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3082 {
3083 peer->weight = group->conf->weight;
3084 }
3085 return 0;
3086}
3087
3088int
3089peer_weight_unset (struct peer *peer)
3090{
3091 struct peer_group *group;
1eb8ef25 3092 struct listnode *node, *nnode;
718e3744 3093
3094 /* Set default weight. */
3095 if (peer_group_active (peer))
3096 peer->weight = peer->group->conf->weight;
3097 else
3098 peer->weight = 0;
3099
3100 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3101
3102 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3103 return 0;
3104
3105 /* peer-group member updates. */
3106 group = peer->group;
1eb8ef25 3107 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3108 {
3109 peer->weight = 0;
3110 }
3111 return 0;
3112}
3113\f
3114int
3115peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3116{
3117 struct peer_group *group;
1eb8ef25 3118 struct listnode *node, *nnode;
718e3744 3119
3120 /* Not for peer group memeber. */
3121 if (peer_group_active (peer))
3122 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3123
3124 /* keepalive value check. */
3125 if (keepalive > 65535)
3126 return BGP_ERR_INVALID_VALUE;
3127
3128 /* Holdtime value check. */
3129 if (holdtime > 65535)
3130 return BGP_ERR_INVALID_VALUE;
3131
3132 /* Holdtime value must be either 0 or greater than 3. */
3133 if (holdtime < 3 && holdtime != 0)
3134 return BGP_ERR_INVALID_VALUE;
3135
3136 /* Set value to the configuration. */
3137 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3138 peer->holdtime = holdtime;
3139 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3140
3141 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3142 return 0;
3143
3144 /* peer-group member updates. */
3145 group = peer->group;
1eb8ef25 3146 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3147 {
3148 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3149 peer->holdtime = group->conf->holdtime;
3150 peer->keepalive = group->conf->keepalive;
3151 }
3152 return 0;
3153}
3154
3155int
3156peer_timers_unset (struct peer *peer)
3157{
3158 struct peer_group *group;
1eb8ef25 3159 struct listnode *node, *nnode;
718e3744 3160
3161 if (peer_group_active (peer))
3162 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3163
3164 /* Clear configuration. */
3165 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3166 peer->keepalive = 0;
3167 peer->holdtime = 0;
3168
3169 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3170 return 0;
3171
3172 /* peer-group member updates. */
3173 group = peer->group;
1eb8ef25 3174 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3175 {
3176 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3177 peer->holdtime = 0;
3178 peer->keepalive = 0;
3179 }
3180
3181 return 0;
3182}
3183\f
3184int
3185peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3186{
3187 if (peer_group_active (peer))
3188 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3189
3190 if (connect > 65535)
3191 return BGP_ERR_INVALID_VALUE;
3192
3193 /* Set value to the configuration. */
3194 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3195 peer->connect = connect;
3196
3197 /* Set value to timer setting. */
3198 peer->v_connect = connect;
3199
3200 return 0;
3201}
3202
3203int
3204peer_timers_connect_unset (struct peer *peer)
3205{
3206 if (peer_group_active (peer))
3207 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3208
3209 /* Clear configuration. */
3210 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3211 peer->connect = 0;
3212
3213 /* Set timer setting to default value. */
3214 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3215
3216 return 0;
3217}
3218\f
3219int
3220peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3221{
3222 if (peer_group_active (peer))
3223 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3224
3225 if (routeadv > 600)
3226 return BGP_ERR_INVALID_VALUE;
3227
3228 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3229 peer->routeadv = routeadv;
3230 peer->v_routeadv = routeadv;
3231
3232 return 0;
3233}
3234
3235int
3236peer_advertise_interval_unset (struct peer *peer)
3237{
3238 if (peer_group_active (peer))
3239 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3240
3241 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3242 peer->routeadv = 0;
3243
3244 if (peer_sort (peer) == BGP_PEER_IBGP)
3245 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3246 else
3247 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3248
3249 return 0;
3250}
3251\f
718e3744 3252/* neighbor interface */
3253int
fd79ac91 3254peer_interface_set (struct peer *peer, const char *str)
718e3744 3255{
3256 if (peer->ifname)
3257 free (peer->ifname);
3258 peer->ifname = strdup (str);
3259
3260 return 0;
3261}
3262
3263int
3264peer_interface_unset (struct peer *peer)
3265{
3266 if (peer->ifname)
3267 free (peer->ifname);
3268 peer->ifname = NULL;
3269
3270 return 0;
3271}
3272\f
3273/* Allow-as in. */
3274int
3275peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3276{
3277 struct peer_group *group;
1eb8ef25 3278 struct listnode *node, *nnode;
718e3744 3279
3280 if (allow_num < 1 || allow_num > 10)
3281 return BGP_ERR_INVALID_VALUE;
3282
3283 if (peer->allowas_in[afi][safi] != allow_num)
3284 {
3285 peer->allowas_in[afi][safi] = allow_num;
3286 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3287 peer_change_action (peer, afi, safi, peer_change_reset_in);
3288 }
3289
3290 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3291 return 0;
3292
3293 group = peer->group;
1eb8ef25 3294 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3295 {
3296 if (peer->allowas_in[afi][safi] != allow_num)
3297 {
3298 peer->allowas_in[afi][safi] = allow_num;
3299 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3300 peer_change_action (peer, afi, safi, peer_change_reset_in);
3301 }
3302
3303 }
3304 return 0;
3305}
3306
3307int
3308peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3309{
3310 struct peer_group *group;
1eb8ef25 3311 struct listnode *node, *nnode;
718e3744 3312
3313 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3314 {
3315 peer->allowas_in[afi][safi] = 0;
3316 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3317 }
3318
3319 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3320 return 0;
3321
3322 group = peer->group;
1eb8ef25 3323 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3324 {
3325 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3326 {
3327 peer->allowas_in[afi][safi] = 0;
3328 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3329 }
3330 }
3331 return 0;
3332}
3333\f
3334int
3335peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3336{
3337 struct bgp *bgp = peer->bgp;
3338 struct peer_group *group;
1eb8ef25 3339 struct listnode *node, *nnode;
718e3744 3340
3341 if (peer_sort (peer) != BGP_PEER_EBGP
3342 && peer_sort (peer) != BGP_PEER_INTERNAL)
3343 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3344
3345 if (bgp->as == as)
3346 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3347
3348 if (peer_group_active (peer))
3349 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3350
3351 if (peer->change_local_as == as &&
3352 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3353 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3354 return 0;
3355
3356 peer->change_local_as = as;
3357 if (no_prepend)
3358 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3359 else
3360 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3361
3362 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3363 {
3364 if (peer->status == Established)
e0701b79 3365 {
3366 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3367 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3368 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3369 }
718e3744 3370 else
3371 BGP_EVENT_ADD (peer, BGP_Stop);
3372
3373 return 0;
3374 }
3375
3376 group = peer->group;
1eb8ef25 3377 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3378 {
3379 peer->change_local_as = as;
3380 if (no_prepend)
3381 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3382 else
3383 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3384
3385 if (peer->status == Established)
e0701b79 3386 {
3387 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3388 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3389 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3390 }
718e3744 3391 else
3392 BGP_EVENT_ADD (peer, BGP_Stop);
3393 }
3394
3395 return 0;
3396}
3397
3398int
3399peer_local_as_unset (struct peer *peer)
3400{
3401 struct peer_group *group;
1eb8ef25 3402 struct listnode *node, *nnode;
718e3744 3403
3404 if (peer_group_active (peer))
3405 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3406
3407 if (! peer->change_local_as)
3408 return 0;
3409
3410 peer->change_local_as = 0;
3411 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3412
3413 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3414 {
3415 if (peer->status == Established)
e0701b79 3416 {
3417 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3418 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3419 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3420 }
718e3744 3421 else
3422 BGP_EVENT_ADD (peer, BGP_Stop);
3423
3424 return 0;
3425 }
3426
3427 group = peer->group;
1eb8ef25 3428 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3429 {
3430 peer->change_local_as = 0;
3431 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3432
3433 if (peer->status == Established)
e0701b79 3434 {
3435 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3436 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3437 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3438 }
718e3744 3439 else
3440 BGP_EVENT_ADD (peer, BGP_Stop);
3441 }
3442 return 0;
3443}
3444\f
0df7c91f
PJ
3445/* Set password for authenticating with the peer. */
3446int
3447peer_password_set (struct peer *peer, const char *password)
3448{
3449 struct listnode *nn, *nnode;
3450 int len = password ? strlen(password) : 0;
3451 int ret = BGP_SUCCESS;
3452
3453 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3454 return BGP_ERR_INVALID_VALUE;
3455
3456 if (peer->password && strcmp (peer->password, password) == 0
3457 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3458 return 0;
3459
3460 if (peer->password)
3461 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3462
3463 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3464
3465 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3466 {
3467 if (peer->status == Established)
3468 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3469 else
3470 BGP_EVENT_ADD (peer, BGP_Stop);
3471
3472 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3473 }
3474
3475 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3476 {
3477 if (peer->password && strcmp (peer->password, password) == 0)
3478 continue;
3479
3480 if (peer->password)
3481 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3482
3483 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3484
3485 if (peer->status == Established)
3486 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3487 else
3488 BGP_EVENT_ADD (peer, BGP_Stop);
3489
3490 if (bgp_md5_set (peer) < 0)
3491 ret = BGP_ERR_TCPSIG_FAILED;
3492 }
3493
3494 return ret;
3495}
3496
3497int
3498peer_password_unset (struct peer *peer)
3499{
3500 struct listnode *nn, *nnode;
3501
3502 if (!peer->password
3503 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3504 return 0;
3505
3506 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3507 {
3508 if (peer_group_active (peer)
3509 && peer->group->conf->password
3510 && strcmp (peer->group->conf->password, peer->password) == 0)
3511 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3512
3513 if (peer->status == Established)
3514 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3515 else
3516 BGP_EVENT_ADD (peer, BGP_Stop);
3517
3518 if (peer->password)
3519 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3520
3521 peer->password = NULL;
3522
3523 bgp_md5_set (peer);
3524
3525 return 0;
3526 }
3527
3528 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3529 peer->password = NULL;
3530
3531 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3532 {
3533 if (!peer->password)
3534 continue;
3535
3536 if (peer->status == Established)
3537 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3538 else
3539 BGP_EVENT_ADD (peer, BGP_Stop);
3540
3541 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3542 peer->password = NULL;
3543
3544 bgp_md5_set (peer);
3545 }
3546
3547 return 0;
3548}
3549\f
718e3744 3550/* Set distribute list to the peer. */
3551int
3552peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 3553 const char *name)
718e3744 3554{
3555 struct bgp_filter *filter;
3556 struct peer_group *group;
1eb8ef25 3557 struct listnode *node, *nnode;
718e3744 3558
3559 if (! peer->afc[afi][safi])
3560 return BGP_ERR_PEER_INACTIVE;
3561
3562 if (direct != FILTER_IN && direct != FILTER_OUT)
3563 return BGP_ERR_INVALID_VALUE;
3564
3565 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3566 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3567
3568 filter = &peer->filter[afi][safi];
3569
3570 if (filter->plist[direct].name)
3571 return BGP_ERR_PEER_FILTER_CONFLICT;
3572
3573 if (filter->dlist[direct].name)
3574 free (filter->dlist[direct].name);
3575 filter->dlist[direct].name = strdup (name);
3576 filter->dlist[direct].alist = access_list_lookup (afi, name);
3577
3578 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3579 return 0;
3580
3581 group = peer->group;
1eb8ef25 3582 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3583 {
3584 filter = &peer->filter[afi][safi];
3585
3586 if (! peer->af_group[afi][safi])
3587 continue;
3588
3589 if (filter->dlist[direct].name)
3590 free (filter->dlist[direct].name);
3591 filter->dlist[direct].name = strdup (name);
3592 filter->dlist[direct].alist = access_list_lookup (afi, name);
3593 }
3594
3595 return 0;
3596}
3597
3598int
3599peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3600{
3601 struct bgp_filter *filter;
3602 struct bgp_filter *gfilter;
3603 struct peer_group *group;
1eb8ef25 3604 struct listnode *node, *nnode;
718e3744 3605
3606 if (! peer->afc[afi][safi])
3607 return BGP_ERR_PEER_INACTIVE;
3608
3609 if (direct != FILTER_IN && direct != FILTER_OUT)
3610 return BGP_ERR_INVALID_VALUE;
3611
3612 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3613 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3614
3615 filter = &peer->filter[afi][safi];
3616
3617 /* apply peer-group filter */
3618 if (peer->af_group[afi][safi])
3619 {
3620 gfilter = &peer->group->conf->filter[afi][safi];
3621
3622 if (gfilter->dlist[direct].name)
3623 {
3624 if (filter->dlist[direct].name)
3625 free (filter->dlist[direct].name);
3626 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3627 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3628 return 0;
3629 }
3630 }
3631
3632 if (filter->dlist[direct].name)
3633 free (filter->dlist[direct].name);
3634 filter->dlist[direct].name = NULL;
3635 filter->dlist[direct].alist = NULL;
3636
3637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3638 return 0;
3639
3640 group = peer->group;
1eb8ef25 3641 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3642 {
3643 filter = &peer->filter[afi][safi];
3644
3645 if (! peer->af_group[afi][safi])
3646 continue;
3647
3648 if (filter->dlist[direct].name)
3649 free (filter->dlist[direct].name);
3650 filter->dlist[direct].name = NULL;
3651 filter->dlist[direct].alist = NULL;
3652 }
3653
3654 return 0;
3655}
3656
3657/* Update distribute list. */
94f2b392 3658static void
718e3744 3659peer_distribute_update (struct access_list *access)
3660{
3661 afi_t afi;
3662 safi_t safi;
3663 int direct;
1eb8ef25 3664 struct listnode *mnode, *mnnode;
3665 struct listnode *node, *nnode;
718e3744 3666 struct bgp *bgp;
3667 struct peer *peer;
3668 struct peer_group *group;
3669 struct bgp_filter *filter;
3670
1eb8ef25 3671 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 3672 {
1eb8ef25 3673 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 3674 {
3675 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3676 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3677 {
3678 filter = &peer->filter[afi][safi];
3679
3680 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3681 {
3682 if (filter->dlist[direct].name)
3683 filter->dlist[direct].alist =
3684 access_list_lookup (afi, filter->dlist[direct].name);
3685 else
3686 filter->dlist[direct].alist = NULL;
3687 }
3688 }
3689 }
1eb8ef25 3690 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 3691 {
3692 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3693 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3694 {
3695 filter = &group->conf->filter[afi][safi];
3696
3697 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3698 {
3699 if (filter->dlist[direct].name)
3700 filter->dlist[direct].alist =
3701 access_list_lookup (afi, filter->dlist[direct].name);
3702 else
3703 filter->dlist[direct].alist = NULL;
3704 }
3705 }
3706 }
3707 }
3708}
3709\f
3710/* Set prefix list to the peer. */
3711int
3712peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 3713 const char *name)
718e3744 3714{
3715 struct bgp_filter *filter;
3716 struct peer_group *group;
1eb8ef25 3717 struct listnode *node, *nnode;
718e3744 3718
3719 if (! peer->afc[afi][safi])
3720 return BGP_ERR_PEER_INACTIVE;
3721
3722 if (direct != FILTER_IN && direct != FILTER_OUT)
3723 return BGP_ERR_INVALID_VALUE;
3724
3725 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3726 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3727
3728 filter = &peer->filter[afi][safi];
3729
3730 if (filter->dlist[direct].name)
3731 return BGP_ERR_PEER_FILTER_CONFLICT;
3732
3733 if (filter->plist[direct].name)
3734 free (filter->plist[direct].name);
3735 filter->plist[direct].name = strdup (name);
3736 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3737
3738 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3739 return 0;
3740
3741 group = peer->group;
1eb8ef25 3742 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3743 {
3744 filter = &peer->filter[afi][safi];
3745
3746 if (! peer->af_group[afi][safi])
3747 continue;
3748
3749 if (filter->plist[direct].name)
3750 free (filter->plist[direct].name);
3751 filter->plist[direct].name = strdup (name);
3752 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3753 }
3754 return 0;
3755}
3756
3757int
3758peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3759{
3760 struct bgp_filter *filter;
3761 struct bgp_filter *gfilter;
3762 struct peer_group *group;
1eb8ef25 3763 struct listnode *node, *nnode;
718e3744 3764
3765 if (! peer->afc[afi][safi])
3766 return BGP_ERR_PEER_INACTIVE;
3767
3768 if (direct != FILTER_IN && direct != FILTER_OUT)
3769 return BGP_ERR_INVALID_VALUE;
3770
3771 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3772 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3773
3774 filter = &peer->filter[afi][safi];
3775
3776 /* apply peer-group filter */
3777 if (peer->af_group[afi][safi])
3778 {
3779 gfilter = &peer->group->conf->filter[afi][safi];
3780
3781 if (gfilter->plist[direct].name)
3782 {
3783 if (filter->plist[direct].name)
3784 free (filter->plist[direct].name);
3785 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3786 filter->plist[direct].plist = gfilter->plist[direct].plist;
3787 return 0;
3788 }
3789 }
3790
3791 if (filter->plist[direct].name)
3792 free (filter->plist[direct].name);
3793 filter->plist[direct].name = NULL;
3794 filter->plist[direct].plist = NULL;
3795
3796 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3797 return 0;
3798
3799 group = peer->group;
1eb8ef25 3800 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3801 {
3802 filter = &peer->filter[afi][safi];
3803
3804 if (! peer->af_group[afi][safi])
3805 continue;
3806
3807 if (filter->plist[direct].name)
3808 free (filter->plist[direct].name);
3809 filter->plist[direct].name = NULL;
3810 filter->plist[direct].plist = NULL;
3811 }
3812
3813 return 0;
3814}
3815
3816/* Update prefix-list list. */
94f2b392 3817static void
718e3744 3818peer_prefix_list_update (struct prefix_list *plist)
3819{
1eb8ef25 3820 struct listnode *mnode, *mnnode;
3821 struct listnode *node, *nnode;
718e3744 3822 struct bgp *bgp;
3823 struct peer *peer;
3824 struct peer_group *group;
3825 struct bgp_filter *filter;
3826 afi_t afi;
3827 safi_t safi;
3828 int direct;
3829
1eb8ef25 3830 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 3831 {
1eb8ef25 3832 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 3833 {
3834 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3835 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3836 {
3837 filter = &peer->filter[afi][safi];
3838
3839 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3840 {
3841 if (filter->plist[direct].name)
3842 filter->plist[direct].plist =
3843 prefix_list_lookup (afi, filter->plist[direct].name);
3844 else
3845 filter->plist[direct].plist = NULL;
3846 }
3847 }
3848 }
1eb8ef25 3849 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 3850 {
3851 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3852 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3853 {
3854 filter = &group->conf->filter[afi][safi];
3855
3856 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3857 {
3858 if (filter->plist[direct].name)
3859 filter->plist[direct].plist =
3860 prefix_list_lookup (afi, filter->plist[direct].name);
3861 else
3862 filter->plist[direct].plist = NULL;
3863 }
3864 }
3865 }
3866 }
3867}
3868\f
3869int
3870peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 3871 const char *name)
718e3744 3872{
3873 struct bgp_filter *filter;
3874 struct peer_group *group;
1eb8ef25 3875 struct listnode *node, *nnode;
718e3744 3876
3877 if (! peer->afc[afi][safi])
3878 return BGP_ERR_PEER_INACTIVE;
3879
3880 if (direct != FILTER_IN && direct != FILTER_OUT)
3881 return BGP_ERR_INVALID_VALUE;
3882
3883 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3884 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3885
3886 filter = &peer->filter[afi][safi];
3887
3888 if (filter->aslist[direct].name)
3889 free (filter->aslist[direct].name);
3890 filter->aslist[direct].name = strdup (name);
3891 filter->aslist[direct].aslist = as_list_lookup (name);
3892
3893 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3894 return 0;
3895
3896 group = peer->group;
1eb8ef25 3897 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3898 {
3899 filter = &peer->filter[afi][safi];
3900
3901 if (! peer->af_group[afi][safi])
3902 continue;
3903
3904 if (filter->aslist[direct].name)
3905 free (filter->aslist[direct].name);
3906 filter->aslist[direct].name = strdup (name);
3907 filter->aslist[direct].aslist = as_list_lookup (name);
3908 }
3909 return 0;
3910}
3911
3912int
3913peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3914{
3915 struct bgp_filter *filter;
3916 struct bgp_filter *gfilter;
3917 struct peer_group *group;
1eb8ef25 3918 struct listnode *node, *nnode;
718e3744 3919
3920 if (! peer->afc[afi][safi])
3921 return BGP_ERR_PEER_INACTIVE;
3922
b5f29603 3923 if (direct != FILTER_IN && direct != FILTER_OUT)
718e3744 3924 return BGP_ERR_INVALID_VALUE;
3925
b5f29603 3926 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
718e3744 3927 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3928
3929 filter = &peer->filter[afi][safi];
3930
3931 /* apply peer-group filter */
3932 if (peer->af_group[afi][safi])
3933 {
3934 gfilter = &peer->group->conf->filter[afi][safi];
3935
3936 if (gfilter->aslist[direct].name)
3937 {
3938 if (filter->aslist[direct].name)
3939 free (filter->aslist[direct].name);
3940 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3941 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3942 return 0;
3943 }
3944 }
3945
3946 if (filter->aslist[direct].name)
3947 free (filter->aslist[direct].name);
3948 filter->aslist[direct].name = NULL;
3949 filter->aslist[direct].aslist = NULL;
3950
3951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3952 return 0;
3953
3954 group = peer->group;
1eb8ef25 3955 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3956 {
3957 filter = &peer->filter[afi][safi];
3958
3959 if (! peer->af_group[afi][safi])
3960 continue;
3961
3962 if (filter->aslist[direct].name)
3963 free (filter->aslist[direct].name);
3964 filter->aslist[direct].name = NULL;
3965 filter->aslist[direct].aslist = NULL;
3966 }
3967
3968 return 0;
3969}
3970
94f2b392 3971static void
66e5cd87 3972peer_aslist_update (void)
718e3744 3973{
3974 afi_t afi;
3975 safi_t safi;
3976 int direct;
1eb8ef25 3977 struct listnode *mnode, *mnnode;
3978 struct listnode *node, *nnode;
718e3744 3979 struct bgp *bgp;
3980 struct peer *peer;
3981 struct peer_group *group;
3982 struct bgp_filter *filter;
3983
1eb8ef25 3984 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 3985 {
1eb8ef25 3986 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 3987 {
3988 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3989 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3990 {
3991 filter = &peer->filter[afi][safi];
3992
3993 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3994 {
3995 if (filter->aslist[direct].name)
3996 filter->aslist[direct].aslist =
3997 as_list_lookup (filter->aslist[direct].name);
3998 else
3999 filter->aslist[direct].aslist = NULL;
4000 }
4001 }
4002 }
1eb8ef25 4003 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 4004 {
4005 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4006 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4007 {
4008 filter = &group->conf->filter[afi][safi];
4009
4010 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4011 {
4012 if (filter->aslist[direct].name)
4013 filter->aslist[direct].aslist =
4014 as_list_lookup (filter->aslist[direct].name);
4015 else
4016 filter->aslist[direct].aslist = NULL;
4017 }
4018 }
4019 }
4020 }
4021}
4022\f
4023/* Set route-map to the peer. */
4024int
4025peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 4026 const char *name)
718e3744 4027{
4028 struct bgp_filter *filter;
4029 struct peer_group *group;
1eb8ef25 4030 struct listnode *node, *nnode;
718e3744 4031
4032 if (! peer->afc[afi][safi])
4033 return BGP_ERR_PEER_INACTIVE;
4034
fee0f4c6 4035 if (direct != RMAP_IN && direct != RMAP_OUT &&
4036 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
718e3744 4037 return BGP_ERR_INVALID_VALUE;
4038
fee0f4c6 4039 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4040 && peer_is_group_member (peer, afi, safi))
718e3744 4041 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4042
4043 filter = &peer->filter[afi][safi];
4044
4045 if (filter->map[direct].name)
4046 free (filter->map[direct].name);
4047
4048 filter->map[direct].name = strdup (name);
4049 filter->map[direct].map = route_map_lookup_by_name (name);
4050
4051 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4052 return 0;
4053
4054 group = peer->group;
1eb8ef25 4055 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4056 {
4057 filter = &peer->filter[afi][safi];
4058
4059 if (! peer->af_group[afi][safi])
4060 continue;
4061
4062 if (filter->map[direct].name)
4063 free (filter->map[direct].name);
4064 filter->map[direct].name = strdup (name);
4065 filter->map[direct].map = route_map_lookup_by_name (name);
4066 }
4067 return 0;
4068}
4069
4070/* Unset route-map from the peer. */
4071int
4072peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4073{
4074 struct bgp_filter *filter;
4075 struct bgp_filter *gfilter;
4076 struct peer_group *group;
1eb8ef25 4077 struct listnode *node, *nnode;
718e3744 4078
4079 if (! peer->afc[afi][safi])
4080 return BGP_ERR_PEER_INACTIVE;
4081
b5f29603 4082 if (direct != RMAP_IN && direct != RMAP_OUT &&
4083 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
718e3744 4084 return BGP_ERR_INVALID_VALUE;
4085
b5f29603 4086 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4087 && peer_is_group_member (peer, afi, safi))
718e3744 4088 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4089
4090 filter = &peer->filter[afi][safi];
4091
4092 /* apply peer-group filter */
4093 if (peer->af_group[afi][safi])
4094 {
4095 gfilter = &peer->group->conf->filter[afi][safi];
4096
4097 if (gfilter->map[direct].name)
4098 {
4099 if (filter->map[direct].name)
4100 free (filter->map[direct].name);
4101 filter->map[direct].name = strdup (gfilter->map[direct].name);
4102 filter->map[direct].map = gfilter->map[direct].map;
4103 return 0;
4104 }
4105 }
4106
4107 if (filter->map[direct].name)
4108 free (filter->map[direct].name);
4109 filter->map[direct].name = NULL;
4110 filter->map[direct].map = NULL;
4111
4112 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4113 return 0;
4114
4115 group = peer->group;
1eb8ef25 4116 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4117 {
4118 filter = &peer->filter[afi][safi];
4119
4120 if (! peer->af_group[afi][safi])
4121 continue;
4122
4123 if (filter->map[direct].name)
4124 free (filter->map[direct].name);
4125 filter->map[direct].name = NULL;
4126 filter->map[direct].map = NULL;
4127 }
4128 return 0;
4129}
4130\f
4131/* Set unsuppress-map to the peer. */
4132int
fd79ac91 4133peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4134 const char *name)
718e3744 4135{
4136 struct bgp_filter *filter;
4137 struct peer_group *group;
1eb8ef25 4138 struct listnode *node, *nnode;
718e3744 4139
4140 if (! peer->afc[afi][safi])
4141 return BGP_ERR_PEER_INACTIVE;
4142
4143 if (peer_is_group_member (peer, afi, safi))
4144 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4145
4146 filter = &peer->filter[afi][safi];
4147
4148 if (filter->usmap.name)
4149 free (filter->usmap.name);
4150
4151 filter->usmap.name = strdup (name);
4152 filter->usmap.map = route_map_lookup_by_name (name);
4153
4154 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4155 return 0;
4156
4157 group = peer->group;
1eb8ef25 4158 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4159 {
4160 filter = &peer->filter[afi][safi];
4161
4162 if (! peer->af_group[afi][safi])
4163 continue;
4164
4165 if (filter->usmap.name)
4166 free (filter->usmap.name);
4167 filter->usmap.name = strdup (name);
4168 filter->usmap.map = route_map_lookup_by_name (name);
4169 }
4170 return 0;
4171}
4172
4173/* Unset route-map from the peer. */
4174int
4175peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4176{
4177 struct bgp_filter *filter;
4178 struct peer_group *group;
1eb8ef25 4179 struct listnode *node, *nnode;
718e3744 4180
4181 if (! peer->afc[afi][safi])
4182 return BGP_ERR_PEER_INACTIVE;
4183
4184 if (peer_is_group_member (peer, afi, safi))
4185 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4186
4187 filter = &peer->filter[afi][safi];
4188
4189 if (filter->usmap.name)
4190 free (filter->usmap.name);
4191 filter->usmap.name = NULL;
4192 filter->usmap.map = NULL;
4193
4194 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4195 return 0;
4196
4197 group = peer->group;
1eb8ef25 4198 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4199 {
4200 filter = &peer->filter[afi][safi];
4201
4202 if (! peer->af_group[afi][safi])
4203 continue;
4204
4205 if (filter->usmap.name)
4206 free (filter->usmap.name);
4207 filter->usmap.name = NULL;
4208 filter->usmap.map = NULL;
4209 }
4210 return 0;
4211}
4212\f
4213int
4214peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
0a486e5f 4215 u_int32_t max, u_char threshold,
4216 int warning, u_int16_t restart)
718e3744 4217{
4218 struct peer_group *group;
1eb8ef25 4219 struct listnode *node, *nnode;
718e3744 4220
4221 if (! peer->afc[afi][safi])
4222 return BGP_ERR_PEER_INACTIVE;
4223
4224 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4225 peer->pmax[afi][safi] = max;
e0701b79 4226 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 4227 peer->pmax_restart[afi][safi] = restart;
718e3744 4228 if (warning)
4229 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4230 else
4231 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4232
4233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4234 return 0;
4235
4236 group = peer->group;
1eb8ef25 4237 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4238 {
4239 if (! peer->af_group[afi][safi])
4240 continue;
4241
4242 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4243 peer->pmax[afi][safi] = max;
e0701b79 4244 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 4245 peer->pmax_restart[afi][safi] = restart;
718e3744 4246 if (warning)
4247 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4248 else
4249 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4250 }
4251 return 0;
4252}
4253
4254int
4255peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4256{
4257 struct peer_group *group;
1eb8ef25 4258 struct listnode *node, *nnode;
718e3744 4259
4260 if (! peer->afc[afi][safi])
4261 return BGP_ERR_PEER_INACTIVE;
4262
4263 /* apply peer-group config */
4264 if (peer->af_group[afi][safi])
4265 {
4266 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4267 PEER_FLAG_MAX_PREFIX))
4268 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4269 else
4270 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4271
4272 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4273 PEER_FLAG_MAX_PREFIX_WARNING))
4274 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4275 else
4276 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4277
4278 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
e0701b79 4279 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
0a486e5f 4280 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
718e3744 4281 return 0;
4282 }
4283
4284 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4285 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4286 peer->pmax[afi][safi] = 0;
0a486e5f 4287 peer->pmax_threshold[afi][safi] = 0;
4288 peer->pmax_restart[afi][safi] = 0;
718e3744 4289
4290 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4291 return 0;
4292
4293 group = peer->group;
1eb8ef25 4294 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4295 {
4296 if (! peer->af_group[afi][safi])
4297 continue;
4298
4299 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4300 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4301 peer->pmax[afi][safi] = 0;
0a486e5f 4302 peer->pmax_threshold[afi][safi] = 0;
4303 peer->pmax_restart[afi][safi] = 0;
718e3744 4304 }
4305 return 0;
4306}
4307\f
4308int
4309peer_clear (struct peer *peer)
4310{
4311 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4312 {
0a486e5f 4313 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4314 {
4315 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4316 if (peer->t_pmax_restart)
4317 {
4318 BGP_TIMER_OFF (peer->t_pmax_restart);
4319 if (BGP_DEBUG (events, EVENTS))
4320 zlog_debug ("%s Maximum-prefix restart timer canceled",
4321 peer->host);
4322 }
4323 BGP_EVENT_ADD (peer, BGP_Start);
4324 return 0;
4325 }
4326
718e3744 4327 peer->v_start = BGP_INIT_START_TIMER;
4328 if (peer->status == Established)
4329 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4330 BGP_NOTIFY_CEASE_ADMIN_RESET);
4331 else
4332 BGP_EVENT_ADD (peer, BGP_Stop);
4333 }
4334 return 0;
4335}
4336
4337int
4338peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4339 enum bgp_clear_type stype)
4340{
4341 if (peer->status != Established)
4342 return 0;
4343
4344 if (! peer->afc[afi][safi])
4345 return BGP_ERR_AF_UNCONFIGURED;
4346
fee0f4c6 4347 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4348 {
4349 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4350 return 0;
4351 bgp_check_local_routes_rsclient (peer, afi, safi);
4352 bgp_soft_reconfig_rsclient (peer, afi, safi);
4353 }
4354
718e3744 4355 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4356 bgp_announce_route (peer, afi, safi);
4357
4358 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4359 {
4360 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4361 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4362 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4363 {
4364 struct bgp_filter *filter = &peer->filter[afi][safi];
4365 u_char prefix_type;
4366
4367 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4368 prefix_type = ORF_TYPE_PREFIX;
4369 else
4370 prefix_type = ORF_TYPE_PREFIX_OLD;
4371
4372 if (filter->plist[FILTER_IN].plist)
4373 {
4374 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4375 bgp_route_refresh_send (peer, afi, safi,
4376 prefix_type, REFRESH_DEFER, 1);
4377 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4378 REFRESH_IMMEDIATE, 0);
4379 }
4380 else
4381 {
4382 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4383 bgp_route_refresh_send (peer, afi, safi,
4384 prefix_type, REFRESH_IMMEDIATE, 1);
4385 else
4386 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4387 }
4388 return 0;
4389 }
4390 }
4391
4392 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4393 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4394 {
4395 /* If neighbor has soft reconfiguration inbound flag.
4396 Use Adj-RIB-In database. */
4397 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4398 bgp_soft_reconfig_in (peer, afi, safi);
4399 else
4400 {
4401 /* If neighbor has route refresh capability, send route refresh
4402 message to the peer. */
4403 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4404 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4405 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4406 else
4407 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4408 }
4409 }
4410 return 0;
4411}
4412\f
fd79ac91 4413/* Display peer uptime.*/
4414/* XXX: why does this function return char * when it takes buffer? */
718e3744 4415char *
4416peer_uptime (time_t uptime2, char *buf, size_t len)
4417{
4418 time_t uptime1;
4419 struct tm *tm;
4420
4421 /* Check buffer length. */
4422 if (len < BGP_UPTIME_LEN)
4423 {
0cd1c32d 4424 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
fd79ac91 4425 /* XXX: should return status instead of buf... */
4426 snprintf (buf, len, "<error> ");
4427 return buf;
718e3744 4428 }
4429
4430 /* If there is no connection has been done before print `never'. */
4431 if (uptime2 == 0)
4432 {
4433 snprintf (buf, len, "never ");
4434 return buf;
4435 }
4436
4437 /* Get current time. */
4438 uptime1 = time (NULL);
4439 uptime1 -= uptime2;
4440 tm = gmtime (&uptime1);
4441
4442 /* Making formatted timer strings. */
4443#define ONE_DAY_SECOND 60*60*24
4444#define ONE_WEEK_SECOND 60*60*24*7
4445
4446 if (uptime1 < ONE_DAY_SECOND)
4447 snprintf (buf, len, "%02d:%02d:%02d",
4448 tm->tm_hour, tm->tm_min, tm->tm_sec);
4449 else if (uptime1 < ONE_WEEK_SECOND)
4450 snprintf (buf, len, "%dd%02dh%02dm",
4451 tm->tm_yday, tm->tm_hour, tm->tm_min);
4452 else
4453 snprintf (buf, len, "%02dw%dd%02dh",
4454 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4455 return buf;
4456}
4457\f
94f2b392 4458static void
718e3744 4459bgp_config_write_filter (struct vty *vty, struct peer *peer,
4460 afi_t afi, safi_t safi)
4461{
4462 struct bgp_filter *filter;
4463 struct bgp_filter *gfilter = NULL;
4464 char *addr;
4465 int in = FILTER_IN;
4466 int out = FILTER_OUT;
4467
4468 addr = peer->host;
4469 filter = &peer->filter[afi][safi];
4470 if (peer->af_group[afi][safi])
4471 gfilter = &peer->group->conf->filter[afi][safi];
4472
4473 /* distribute-list. */
4474 if (filter->dlist[in].name)
4475 if (! gfilter || ! gfilter->dlist[in].name
4476 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4477 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4478 filter->dlist[in].name, VTY_NEWLINE);
4479 if (filter->dlist[out].name && ! gfilter)
4480 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4481 filter->dlist[out].name, VTY_NEWLINE);
4482
4483 /* prefix-list. */
4484 if (filter->plist[in].name)
4485 if (! gfilter || ! gfilter->plist[in].name
4486 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4487 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4488 filter->plist[in].name, VTY_NEWLINE);
4489 if (filter->plist[out].name && ! gfilter)
4490 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4491 filter->plist[out].name, VTY_NEWLINE);
4492
4493 /* route-map. */
fee0f4c6 4494 if (filter->map[RMAP_IN].name)
4495 if (! gfilter || ! gfilter->map[RMAP_IN].name
4496 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
718e3744 4497 vty_out (vty, " neighbor %s route-map %s in%s", addr,
fee0f4c6 4498 filter->map[RMAP_IN].name, VTY_NEWLINE);
4499 if (filter->map[RMAP_OUT].name && ! gfilter)
718e3744 4500 vty_out (vty, " neighbor %s route-map %s out%s", addr,
fee0f4c6 4501 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4502 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4503 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4504 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4505 if (filter->map[RMAP_EXPORT].name)
4506 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4507 || strcmp (filter->map[RMAP_EXPORT].name,
4508 gfilter->map[RMAP_EXPORT].name) != 0)
4509 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4510 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
718e3744 4511
4512 /* unsuppress-map */
4513 if (filter->usmap.name && ! gfilter)
4514 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4515 filter->usmap.name, VTY_NEWLINE);
4516
4517 /* filter-list. */
4518 if (filter->aslist[in].name)
4519 if (! gfilter || ! gfilter->aslist[in].name
4520 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4521 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4522 filter->aslist[in].name, VTY_NEWLINE);
4523 if (filter->aslist[out].name && ! gfilter)
4524 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4525 filter->aslist[out].name, VTY_NEWLINE);
4526}
4527
4528/* BGP peer configuration display function. */
94f2b392 4529static void
718e3744 4530bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4531 struct peer *peer, afi_t afi, safi_t safi)
4532{
4533 struct bgp_filter *filter;
4534 struct peer *g_peer = NULL;
4535 char buf[SU_ADDRSTRLEN];
4536 char *addr;
4537
4538 filter = &peer->filter[afi][safi];
4539 addr = peer->host;
4540 if (peer_group_active (peer))
4541 g_peer = peer->group->conf;
4542
4543 /************************************
4544 ****** Global to the neighbor ******
4545 ************************************/
4546 if (afi == AFI_IP && safi == SAFI_UNICAST)
4547 {
4548 /* remote-as. */
4549 if (! peer_group_active (peer))
4550 {
4551 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4552 vty_out (vty, " neighbor %s peer-group%s", addr,
4553 VTY_NEWLINE);
4554 if (peer->as)
aea339f7 4555 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
718e3744 4556 VTY_NEWLINE);
4557 }
4558 else
4559 {
4560 if (! g_peer->as)
aea339f7 4561 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
718e3744 4562 VTY_NEWLINE);
4563 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4564 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4565 peer->group->name, VTY_NEWLINE);
4566 }
4567
4568 /* local-as. */
4569 if (peer->change_local_as)
4570 if (! peer_group_active (peer))
aea339f7 4571 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
718e3744 4572 peer->change_local_as,
4573 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4574 " no-prepend" : "", VTY_NEWLINE);
4575
4576 /* Description. */
4577 if (peer->desc)
4578 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4579 VTY_NEWLINE);
4580
4581 /* Shutdown. */
4582 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4583 if (! peer_group_active (peer) ||
4584 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4585 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4586
0df7c91f
PJ
4587 /* Password. */
4588 if (peer->password)
4589 if (!peer_group_active (peer)
4590 || ! g_peer->password
4591 || strcmp (peer->password, g_peer->password) != 0)
4592 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4593 VTY_NEWLINE);
4594
718e3744 4595 /* BGP port. */
4596 if (peer->port != BGP_PORT_DEFAULT)
0df7c91f 4597 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
718e3744 4598 VTY_NEWLINE);
4599
4600 /* Local interface name. */
4601 if (peer->ifname)
4602 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4603 VTY_NEWLINE);
4604
4605 /* Passive. */
4606 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4607 if (! peer_group_active (peer) ||
4608 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4609 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4610
4611 /* EBGP multihop. */
4612 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4613 if (! peer_group_active (peer) ||
4614 g_peer->ttl != peer->ttl)
4615 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4616 VTY_NEWLINE);
4617
6ffd2079 4618 /* disable-connected-check. */
4619 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
718e3744 4620 if (! peer_group_active (peer) ||
6ffd2079 4621 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4622 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
718e3744 4623
4624 /* Update-source. */
4625 if (peer->update_if)
4626 if (! peer_group_active (peer) || ! g_peer->update_if
4627 || strcmp (g_peer->update_if, peer->update_if) != 0)
4628 vty_out (vty, " neighbor %s update-source %s%s", addr,
4629 peer->update_if, VTY_NEWLINE);
4630 if (peer->update_source)
4631 if (! peer_group_active (peer) || ! g_peer->update_source
4632 || sockunion_cmp (g_peer->update_source,
4633 peer->update_source) != 0)
4634 vty_out (vty, " neighbor %s update-source %s%s", addr,
4635 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4636 VTY_NEWLINE);
4637
718e3744 4638 /* advertisement-interval */
4639 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4640 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4641 addr, peer->v_routeadv, VTY_NEWLINE);
4642
4643 /* timers. */
4644 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4645 && ! peer_group_active (peer))
4646 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4647 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4648
4649 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4650 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4651 peer->connect, VTY_NEWLINE);
4652
4653 /* Default weight. */
4654 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4655 if (! peer_group_active (peer) ||
4656 g_peer->weight != peer->weight)
4657 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4658 VTY_NEWLINE);
4659
718e3744 4660 /* Dynamic capability. */
4661 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4662 if (! peer_group_active (peer) ||
4663 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4664 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4665 VTY_NEWLINE);
4666
4667 /* dont capability negotiation. */
4668 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4669 if (! peer_group_active (peer) ||
4670 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4671 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4672 VTY_NEWLINE);
4673
4674 /* override capability negotiation. */
4675 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4676 if (! peer_group_active (peer) ||
4677 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4678 vty_out (vty, " neighbor %s override-capability%s", addr,
4679 VTY_NEWLINE);
4680
4681 /* strict capability negotiation. */
4682 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4683 if (! peer_group_active (peer) ||
4684 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4685 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4686 VTY_NEWLINE);
4687
4688 if (! peer_group_active (peer))
4689 {
4690 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4691 {
4692 if (peer->afc[AFI_IP][SAFI_UNICAST])
4693 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4694 }
4695 else
4696 {
4697 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4698 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4699 }
4700 }
4701 }
4702
4703
4704 /************************************
4705 ****** Per AF to the neighbor ******
4706 ************************************/
4707
4708 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4709 {
4710 if (peer->af_group[afi][safi])
4711 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4712 peer->group->name, VTY_NEWLINE);
4713 else
4714 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4715 }
4716
4717 /* ORF capability. */
4718 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4719 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4720 if (! peer->af_group[afi][safi])
4721 {
4722 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4723
4724 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4725 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4726 vty_out (vty, " both");
4727 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4728 vty_out (vty, " send");
4729 else
4730 vty_out (vty, " receive");
4731 vty_out (vty, "%s", VTY_NEWLINE);
4732 }
4733
4734 /* Route reflector client. */
4735 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4736 && ! peer->af_group[afi][safi])
4737 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4738 VTY_NEWLINE);
4739
4740 /* Nexthop self. */
4741 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4742 && ! peer->af_group[afi][safi])
4743 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4744
4745 /* Remove private AS. */
4746 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4747 && ! peer->af_group[afi][safi])
4748 vty_out (vty, " neighbor %s remove-private-AS%s",
4749 addr, VTY_NEWLINE);
4750
4751 /* send-community print. */
4752 if (! peer->af_group[afi][safi])
4753 {
4754 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4755 {
4756 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4757 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4758 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4759 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4760 vty_out (vty, " neighbor %s send-community extended%s",
4761 addr, VTY_NEWLINE);
4762 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4763 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4764 }
4765 else
4766 {
4767 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4768 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4769 vty_out (vty, " no neighbor %s send-community both%s",
4770 addr, VTY_NEWLINE);
4771 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4772 vty_out (vty, " no neighbor %s send-community extended%s",
4773 addr, VTY_NEWLINE);
4774 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4775 vty_out (vty, " no neighbor %s send-community%s",
4776 addr, VTY_NEWLINE);
4777 }
4778 }
4779
4780 /* Default information */
4781 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4782 && ! peer->af_group[afi][safi])
4783 {
4784 vty_out (vty, " neighbor %s default-originate", addr);
4785 if (peer->default_rmap[afi][safi].name)
4786 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4787 vty_out (vty, "%s", VTY_NEWLINE);
4788 }
4789
4790 /* Soft reconfiguration inbound. */
4791 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4792 if (! peer->af_group[afi][safi] ||
4793 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4794 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4795 VTY_NEWLINE);
4796
4797 /* maximum-prefix. */
4798 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4799 if (! peer->af_group[afi][safi]
4800 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
e0701b79 4801 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
718e3744 4802 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4803 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
e0701b79 4804 {
0a486e5f 4805 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4806 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4807 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4808 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4809 vty_out (vty, " warning-only");
4810 if (peer->pmax_restart[afi][safi])
4811 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4812 vty_out (vty, "%s", VTY_NEWLINE);
e0701b79 4813 }
718e3744 4814
4815 /* Route server client. */
4816 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4817 && ! peer->af_group[afi][safi])
4818 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4819
4820 /* Allow AS in. */
4821 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4822 if (! peer_group_active (peer)
4823 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4824 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4825 {
4826 if (peer->allowas_in[afi][safi] == 3)
4827 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4828 else
4829 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4830 peer->allowas_in[afi][safi], VTY_NEWLINE);
4831 }
4832
4833 /* Filter. */
4834 bgp_config_write_filter (vty, peer, afi, safi);
4835
4836 /* atribute-unchanged. */
4837 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4838 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4839 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4840 && ! peer->af_group[afi][safi])
4841 {
4842 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4843 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4844 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4845 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4846 else
4847 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4848 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4849 " as-path" : "",
4850 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4851 " next-hop" : "",
4852 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4853 " med" : "", VTY_NEWLINE);
4854 }
4855}
4856
4857/* Display "address-family" configuration header. */
4858void
4859bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4860 int *write)
4861{
4862 if (*write)
4863 return;
4864
4865 if (afi == AFI_IP && safi == SAFI_UNICAST)
4866 return;
4867
4868 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4869
4870 if (afi == AFI_IP)
4871 {
4872 if (safi == SAFI_MULTICAST)
4873 vty_out (vty, "ipv4 multicast");
4874 else if (safi == SAFI_MPLS_VPN)
4875 vty_out (vty, "vpnv4 unicast");
4876 }
4877 else if (afi == AFI_IP6)
37a217a5
PJ
4878 {
4879 vty_out (vty, "ipv6");
4880
4881 if (safi == SAFI_MULTICAST)
4882 vty_out (vty, " multicast");
4883 }
718e3744 4884
4885 vty_out (vty, "%s", VTY_NEWLINE);
4886
4887 *write = 1;
4888}
4889
4890/* Address family based peer configuration display. */
94f2b392 4891static int
718e3744 4892bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4893 safi_t safi)
4894{
4895 int write = 0;
4896 struct peer *peer;
4897 struct peer_group *group;
1eb8ef25 4898 struct listnode *node, *nnode;
718e3744 4899
4900 bgp_config_write_network (vty, bgp, afi, safi, &write);
4901
4902 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4903
1eb8ef25 4904 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 4905 {
4906 if (group->conf->afc[afi][safi])
4907 {
4908 bgp_config_write_family_header (vty, afi, safi, &write);
4909 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4910 }
4911 }
1eb8ef25 4912 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 4913 {
4914 if (peer->afc[afi][safi])
4915 {
4916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4917 {
4918 bgp_config_write_family_header (vty, afi, safi, &write);
4919 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4920 }
4921 }
4922 }
4923 if (write)
4924 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4925
4926 return write;
4927}
4928
4929int
4930bgp_config_write (struct vty *vty)
4931{
4932 int write = 0;
4933 struct bgp *bgp;
4934 struct peer_group *group;
4935 struct peer *peer;
1eb8ef25 4936 struct listnode *node, *nnode;
4937 struct listnode *mnode, *mnnode;
718e3744 4938
4939 /* BGP Multiple instance. */
4940 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4941 {
4942 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4943 write++;
4944 }
4945
4946 /* BGP Config type. */
4947 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4948 {
4949 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4950 write++;
4951 }
4952
4953 /* BGP configuration. */
1eb8ef25 4954 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 4955 {
4956 if (write)
4957 vty_out (vty, "!%s", VTY_NEWLINE);
4958
4959 /* Router bgp ASN */
aea339f7 4960 vty_out (vty, "router bgp %u", bgp->as);
718e3744 4961
4962 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4963 {
4964 if (bgp->name)
4965 vty_out (vty, " view %s", bgp->name);
4966 }
4967 vty_out (vty, "%s", VTY_NEWLINE);
4968
4969 /* No Synchronization */
4970 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4971 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4972
4973 /* BGP fast-external-failover. */
4974 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4975 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4976
4977 /* BGP router ID. */
4978 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4979 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4980 VTY_NEWLINE);
4981
848973c7 4982 /* BGP log-neighbor-changes. */
4983 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4984 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4985
718e3744 4986 /* BGP configuration. */
4987 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4988 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4989
4990 /* BGP default ipv4-unicast. */
4991 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4992 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4993
4994 /* BGP default local-preference. */
4995 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4996 vty_out (vty, " bgp default local-preference %d%s",
4997 bgp->default_local_pref, VTY_NEWLINE);
4998
4999 /* BGP client-to-client reflection. */
5000 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5001 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5002
5003 /* BGP cluster ID. */
5004 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5005 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5006 VTY_NEWLINE);
5007
e0701b79 5008 /* Confederation identifier*/
718e3744 5009 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
e0701b79 5010 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5011 VTY_NEWLINE);
5012
5013 /* Confederation peer */
5014 if (bgp->confed_peers_cnt > 0)
718e3744 5015 {
e0701b79 5016 int i;
718e3744 5017
e0701b79 5018 vty_out (vty, " bgp confederation peers");
718e3744 5019
e0701b79 5020 for (i = 0; i < bgp->confed_peers_cnt; i++)
aea339f7 5021 vty_out(vty, " %u", bgp->confed_peers[i]);
718e3744 5022
e0701b79 5023 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 5024 }
5025
5026 /* BGP enforce-first-as. */
5027 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5028 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5029
5030 /* BGP deterministic-med. */
5031 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5032 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
538621f2 5033
5034 /* BGP graceful-restart. */
93406d87 5035 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5036 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5037 bgp->stalepath_time, VTY_NEWLINE);
538621f2 5038 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5039 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5040
718e3744 5041 /* BGP bestpath method. */
5042 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5043 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
6811845b 5044 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5045 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
718e3744 5046 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5047 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5048 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5049 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5050 {
5051 vty_out (vty, " bgp bestpath med");
5052 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5053 vty_out (vty, " confed");
5054 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5055 vty_out (vty, " missing-as-worst");
5056 vty_out (vty, "%s", VTY_NEWLINE);
5057 }
5058
5059 /* BGP network import check. */
5060 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5061 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5062
5063 /* BGP scan interval. */
5064 bgp_config_write_scan_time (vty);
5065
5066 /* BGP flag dampening. */
5067 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5068 BGP_CONFIG_DAMPENING))
5069 bgp_config_write_damp (vty);
5070
5071 /* BGP static route configuration. */
5072 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5073
5074 /* BGP redistribute configuration. */
5075 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5076
5077 /* BGP timers configuration. */
5078 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5079 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5080 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5081 bgp->default_holdtime, VTY_NEWLINE);
5082
5083 /* peer-group */
1eb8ef25 5084 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5085 {
5086 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5087 }
5088
5089 /* Normal neighbor configuration. */
1eb8ef25 5090 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5091 {
5092 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5093 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5094 }
5095
5096 /* Distance configuration. */
5097 bgp_config_write_distance (vty, bgp);
5098
5099 /* No auto-summary */
5100 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5101 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5102
5103 /* IPv4 multicast configuration. */
5104 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5105
5106 /* IPv4 VPN configuration. */
5107 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5108
5109 /* IPv6 unicast configuration. */
5110 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5111
37a217a5
PJ
5112 /* IPv6 multicast configuration. */
5113 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5114
718e3744 5115 write++;
5116 }
5117 return write;
5118}
5119
5120void
94f2b392 5121bgp_master_init (void)
718e3744 5122{
5123 memset (&bgp_master, 0, sizeof (struct bgp_master));
5124
5125 bm = &bgp_master;
5126 bm->bgp = list_new ();
0df7c91f 5127 bm->listen_sockets = list_new ();
718e3744 5128 bm->port = BGP_PORT_DEFAULT;
5129 bm->master = thread_master_create ();
5130 bm->start_time = time (NULL);
5131}
200df115 5132
718e3744 5133\f
5134void
94f2b392 5135bgp_init (void)
718e3744 5136{
718e3744 5137 /* BGP VTY commands installation. */
5138 bgp_vty_init ();
5139
5140 /* Create BGP server socket. */
3a02d1f7 5141 bgp_socket (NULL, bm->port, bm->address);
718e3744 5142
5143 /* Init zebra. */
5144 bgp_zebra_init ();
5145
5146 /* BGP inits. */
5147 bgp_attr_init ();
5148 bgp_debug_init ();
5149 bgp_dump_init ();
5150 bgp_route_init ();
5151 bgp_route_map_init ();
5152 bgp_scan_init ();
5153 bgp_mplsvpn_init ();
5154
5155 /* Access list initialize. */
5156 access_list_init ();
5157 access_list_add_hook (peer_distribute_update);
5158 access_list_delete_hook (peer_distribute_update);
5159
5160 /* Filter list initialize. */
5161 bgp_filter_init ();
5162 as_list_add_hook (peer_aslist_update);
5163 as_list_delete_hook (peer_aslist_update);
5164
5165 /* Prefix list initialize.*/
5166 prefix_list_init ();
5167 prefix_list_add_hook (peer_prefix_list_update);
5168 prefix_list_delete_hook (peer_prefix_list_update);
5169
5170 /* Community list initialize. */
5171 bgp_clist = community_list_init ();
5172
5173#ifdef HAVE_SNMP
5174 bgp_snmp_init ();
5175#endif /* HAVE_SNMP */
5176}
545acafb 5177
5178void
66e5cd87 5179bgp_terminate (void)
545acafb 5180{
545acafb 5181 struct bgp *bgp;
5182 struct peer *peer;
1eb8ef25 5183 struct listnode *node, *nnode;
5184 struct listnode *mnode, *mnnode;
545acafb 5185
1eb8ef25 5186 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5187 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
545acafb 5188 if (peer->status == Established)
5189 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5190 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
1eb8ef25 5191
545acafb 5192 bgp_cleanup_routes ();
acde4b86 5193
e210cf9f 5194 if (bm->process_main_queue)
acde4b86
SH
5195 {
5196 work_queue_free (bm->process_main_queue);
5197 bm->process_main_queue = NULL;
5198 }
e210cf9f 5199 if (bm->process_rsclient_queue)
acde4b86
SH
5200 {
5201 work_queue_free (bm->process_rsclient_queue);
5202 bm->process_rsclient_queue = NULL;
5203 }
545acafb 5204}