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