]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
Fixup of warnings in the code
[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"
3f9c7369 38#include "queue.h"
88177fe3 39#include "zclient.h"
7f342629 40#include "bfd.h"
718e3744 41
42#include "bgpd/bgpd.h"
43#include "bgpd/bgp_table.h"
44#include "bgpd/bgp_aspath.h"
45#include "bgpd/bgp_route.h"
46#include "bgpd/bgp_dump.h"
47#include "bgpd/bgp_debug.h"
48#include "bgpd/bgp_community.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_regex.h"
51#include "bgpd/bgp_clist.h"
52#include "bgpd/bgp_fsm.h"
53#include "bgpd/bgp_packet.h"
54#include "bgpd/bgp_zebra.h"
55#include "bgpd/bgp_open.h"
56#include "bgpd/bgp_filter.h"
57#include "bgpd/bgp_nexthop.h"
58#include "bgpd/bgp_damp.h"
59#include "bgpd/bgp_mplsvpn.h"
60#include "bgpd/bgp_advertise.h"
61#include "bgpd/bgp_network.h"
62#include "bgpd/bgp_vty.h"
165b5fff 63#include "bgpd/bgp_mpath.h"
fc9a856f 64#include "bgpd/bgp_nht.h"
718e3744 65#ifdef HAVE_SNMP
66#include "bgpd/bgp_snmp.h"
67#endif /* HAVE_SNMP */
3f9c7369 68#include "bgpd/bgp_updgrp.h"
c43ed2e4 69#include "bgpd/bgp_bfd.h"
3f9c7369 70
718e3744 71/* BGP process wide configuration. */
72static struct bgp_master bgp_master;
73
18a6dce6 74extern struct in_addr router_id_zebra;
75
718e3744 76/* BGP process wide configuration pointer to export. */
77struct bgp_master *bm;
78
79/* BGP community-list. */
80struct community_list_handler *bgp_clist;
6b0655a2 81
1ff9a340
DS
82
83static inline void
84bgp_session_reset(struct peer *peer)
85{
86 if (peer->doppelganger && (peer->doppelganger->status != Deleted)
87 && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
88 peer_delete(peer->doppelganger);
89
90 BGP_EVENT_ADD (peer, BGP_Stop);
91}
92
93/*
94 * During session reset, we may delete the doppelganger peer, which would
95 * be the next node to the current node. If the session reset was invoked
96 * during walk of peer list, we would end up accessing the freed next
97 * node. This function moves the next node along.
98 */
99static inline void
100bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
101{
102 struct listnode *n;
103 struct peer *npeer;
104
105 n = (nnode) ? *nnode : NULL;
106 npeer = (n) ? listgetdata(n) : NULL;
107
108 if (peer->doppelganger && (peer->doppelganger->status != Deleted)
109 && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
110 {
111 if (peer->doppelganger == npeer)
112 /* nnode and *nnode are confirmed to be non-NULL here */
113 *nnode = (*nnode)->next;
114 peer_delete(peer->doppelganger);
115 }
116
117 BGP_EVENT_ADD (peer, BGP_Stop);
118}
119
718e3744 120/* BGP global flag manipulation. */
121int
122bgp_option_set (int flag)
123{
124 switch (flag)
125 {
126 case BGP_OPT_NO_FIB:
127 case BGP_OPT_MULTIPLE_INSTANCE:
128 case BGP_OPT_CONFIG_CISCO:
cccbc015 129 case BGP_OPT_NO_LISTEN:
718e3744 130 SET_FLAG (bm->options, flag);
131 break;
132 default:
133 return BGP_ERR_INVALID_FLAG;
718e3744 134 }
135 return 0;
136}
137
138int
139bgp_option_unset (int flag)
140{
141 switch (flag)
142 {
143 case BGP_OPT_MULTIPLE_INSTANCE:
144 if (listcount (bm->bgp) > 1)
145 return BGP_ERR_MULTIPLE_INSTANCE_USED;
146 /* Fall through. */
147 case BGP_OPT_NO_FIB:
148 case BGP_OPT_CONFIG_CISCO:
149 UNSET_FLAG (bm->options, flag);
150 break;
151 default:
152 return BGP_ERR_INVALID_FLAG;
718e3744 153 }
154 return 0;
155}
156
157int
158bgp_option_check (int flag)
159{
160 return CHECK_FLAG (bm->options, flag);
161}
6b0655a2 162
718e3744 163/* BGP flag manipulation. */
164int
165bgp_flag_set (struct bgp *bgp, int flag)
166{
167 SET_FLAG (bgp->flags, flag);
168 return 0;
169}
170
171int
172bgp_flag_unset (struct bgp *bgp, int flag)
173{
174 UNSET_FLAG (bgp->flags, flag);
175 return 0;
176}
177
178int
179bgp_flag_check (struct bgp *bgp, int flag)
180{
181 return CHECK_FLAG (bgp->flags, flag);
182}
6b0655a2 183
718e3744 184/* Internal function to set BGP structure configureation flag. */
185static void
186bgp_config_set (struct bgp *bgp, int config)
187{
188 SET_FLAG (bgp->config, config);
189}
190
191static void
192bgp_config_unset (struct bgp *bgp, int config)
193{
194 UNSET_FLAG (bgp->config, config);
195}
196
197static int
198bgp_config_check (struct bgp *bgp, int config)
199{
200 return CHECK_FLAG (bgp->config, config);
201}
6b0655a2 202
718e3744 203/* Set BGP router identifier. */
204int
205bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
206{
207 struct peer *peer;
1eb8ef25 208 struct listnode *node, *nnode;
718e3744 209
210 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
211 && IPV4_ADDR_SAME (&bgp->router_id, id))
212 return 0;
213
214 IPV4_ADDR_COPY (&bgp->router_id, id);
215 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
216
217 /* Set all peer's local identifier with this value. */
1eb8ef25 218 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 219 {
220 IPV4_ADDR_COPY (&peer->local_id, id);
221
6aa136f1 222 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 223 {
224 peer->last_reset = PEER_DOWN_RID_CHANGE;
225 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
226 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
227 }
718e3744 228 }
229 return 0;
230}
231
718e3744 232/* BGP's cluster-id control. */
233int
234bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
235{
236 struct peer *peer;
1eb8ef25 237 struct listnode *node, *nnode;
718e3744 238
239 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
240 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
241 return 0;
242
243 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
244 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
245
246 /* Clear all IBGP peer. */
1eb8ef25 247 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 248 {
6d85b15b 249 if (peer->sort != BGP_PEER_IBGP)
718e3744 250 continue;
251
6aa136f1 252 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 253 {
254 peer->last_reset = PEER_DOWN_CLID_CHANGE;
255 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
256 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
257 }
718e3744 258 }
259 return 0;
260}
261
262int
263bgp_cluster_id_unset (struct bgp *bgp)
264{
265 struct peer *peer;
1eb8ef25 266 struct listnode *node, *nnode;
718e3744 267
268 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
269 return 0;
270
271 bgp->cluster_id.s_addr = 0;
272 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
273
274 /* Clear all IBGP peer. */
1eb8ef25 275 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 276 {
6d85b15b 277 if (peer->sort != BGP_PEER_IBGP)
718e3744 278 continue;
279
6aa136f1 280 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 281 {
282 peer->last_reset = PEER_DOWN_CLID_CHANGE;
283 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
284 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
285 }
718e3744 286 }
287 return 0;
288}
6b0655a2 289
65957886
SH
290/* time_t value that is monotonicly increasing
291 * and uneffected by adjustments to system clock
292 */
293time_t bgp_clock (void)
294{
295 struct timeval tv;
296
297 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
298 return tv.tv_sec;
299}
300
718e3744 301/* BGP timer configuration. */
302int
303bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
304{
305 bgp->default_keepalive = (keepalive < holdtime / 3
306 ? keepalive : holdtime / 3);
307 bgp->default_holdtime = holdtime;
308
309 return 0;
310}
311
312int
313bgp_timers_unset (struct bgp *bgp)
314{
315 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
316 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
317
318 return 0;
319}
6b0655a2 320
718e3744 321/* BGP confederation configuration. */
322int
323bgp_confederation_id_set (struct bgp *bgp, as_t as)
324{
325 struct peer *peer;
1eb8ef25 326 struct listnode *node, *nnode;
718e3744 327 int already_confed;
328
329 if (as == 0)
330 return BGP_ERR_INVALID_AS;
331
332 /* Remember - were we doing confederation before? */
333 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
334 bgp->confed_id = as;
335 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
336
337 /* If we were doing confederation already, this is just an external
338 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
339 were not doing confederation before, reset all EBGP sessions. */
1eb8ef25 340 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 341 {
342 /* We're looking for peers who's AS is not local or part of our
343 confederation. */
344 if (already_confed)
345 {
346 if (peer_sort (peer) == BGP_PEER_EBGP)
347 {
348 peer->local_as = as;
6aa136f1 349 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 350 {
351 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
352 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
353 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
354 }
718e3744 355 else
1ff9a340 356 bgp_session_reset_safe(peer, &nnode);
718e3744 357 }
358 }
359 else
360 {
361 /* Not doign confederation before, so reset every non-local
362 session */
363 if (peer_sort (peer) != BGP_PEER_IBGP)
364 {
365 /* Reset the local_as to be our EBGP one */
366 if (peer_sort (peer) == BGP_PEER_EBGP)
367 peer->local_as = as;
6aa136f1 368 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 369 {
370 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
371 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
372 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
373 }
718e3744 374 else
1ff9a340 375 bgp_session_reset_safe(peer, &nnode);
718e3744 376 }
377 }
378 }
379 return 0;
380}
381
382int
383bgp_confederation_id_unset (struct bgp *bgp)
384{
385 struct peer *peer;
1eb8ef25 386 struct listnode *node, *nnode;
718e3744 387
388 bgp->confed_id = 0;
389 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
390
1eb8ef25 391 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 392 {
393 /* We're looking for peers who's AS is not local */
394 if (peer_sort (peer) != BGP_PEER_IBGP)
395 {
396 peer->local_as = bgp->as;
6aa136f1 397 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 398 {
399 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
400 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
401 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
402 }
403
718e3744 404 else
1ff9a340 405 bgp_session_reset_safe(peer, &nnode);
718e3744 406 }
407 }
408 return 0;
409}
410
411/* Is an AS part of the confed or not? */
412int
413bgp_confederation_peers_check (struct bgp *bgp, as_t as)
414{
415 int i;
416
417 if (! bgp)
418 return 0;
419
420 for (i = 0; i < bgp->confed_peers_cnt; i++)
421 if (bgp->confed_peers[i] == as)
422 return 1;
423
424 return 0;
425}
426
427/* Add an AS to the confederation set. */
428int
429bgp_confederation_peers_add (struct bgp *bgp, as_t as)
430{
431 struct peer *peer;
1eb8ef25 432 struct listnode *node, *nnode;
718e3744 433
434 if (! bgp)
435 return BGP_ERR_INVALID_BGP;
436
437 if (bgp->as == as)
438 return BGP_ERR_INVALID_AS;
439
440 if (bgp_confederation_peers_check (bgp, as))
441 return -1;
442
443 if (bgp->confed_peers)
444 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
445 bgp->confed_peers,
446 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
447 else
448 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
449 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
450
451 bgp->confed_peers[bgp->confed_peers_cnt] = as;
452 bgp->confed_peers_cnt++;
453
454 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
455 {
1eb8ef25 456 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 457 {
458 if (peer->as == as)
459 {
460 peer->local_as = bgp->as;
6aa136f1 461 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 462 {
463 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
466 }
718e3744 467 else
1ff9a340 468 bgp_session_reset_safe(peer, &nnode);
718e3744 469 }
470 }
471 }
472 return 0;
473}
474
475/* Delete an AS from the confederation set. */
476int
477bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
478{
479 int i;
480 int j;
481 struct peer *peer;
1eb8ef25 482 struct listnode *node, *nnode;
718e3744 483
484 if (! bgp)
485 return -1;
486
487 if (! bgp_confederation_peers_check (bgp, as))
488 return -1;
489
490 for (i = 0; i < bgp->confed_peers_cnt; i++)
491 if (bgp->confed_peers[i] == as)
492 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
493 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
494
495 bgp->confed_peers_cnt--;
496
497 if (bgp->confed_peers_cnt == 0)
498 {
499 if (bgp->confed_peers)
500 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
501 bgp->confed_peers = NULL;
502 }
503 else
504 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
505 bgp->confed_peers,
506 bgp->confed_peers_cnt * sizeof (as_t));
507
508 /* Now reset any peer who's remote AS has just been removed from the
509 CONFED */
510 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
511 {
1eb8ef25 512 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 513 {
514 if (peer->as == as)
515 {
516 peer->local_as = bgp->confed_id;
6aa136f1 517 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 518 {
519 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
520 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
521 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
522 }
718e3744 523 else
1ff9a340 524 bgp_session_reset_safe(peer, &nnode);
718e3744 525 }
526 }
527 }
528
529 return 0;
530}
6b0655a2 531
718e3744 532/* Local preference configuration. */
533int
534bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
535{
536 if (! bgp)
537 return -1;
538
718e3744 539 bgp->default_local_pref = local_pref;
540
541 return 0;
542}
543
544int
545bgp_default_local_preference_unset (struct bgp *bgp)
546{
547 if (! bgp)
548 return -1;
549
718e3744 550 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
551
552 return 0;
553}
6b0655a2 554
3f9c7369
DS
555/* Local preference configuration. */
556int
557bgp_default_subgroup_pkt_queue_max_set (struct bgp *bgp, u_int32_t queue_size)
558{
559 if (! bgp)
560 return -1;
561
562 bgp->default_subgroup_pkt_queue_max = queue_size;
563
564 return 0;
565}
566
567int
568bgp_default_subgroup_pkt_queue_max_unset (struct bgp *bgp)
569{
570 if (! bgp)
571 return -1;
572 bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
573
574 return 0;
575}
576
f14e6fdb
DS
577/* Listen limit configuration. */
578int
579bgp_listen_limit_set (struct bgp *bgp, int listen_limit)
580{
581 if (! bgp)
582 return -1;
583
584 bgp->dynamic_neighbors_limit = listen_limit;
585
586 return 0;
587}
588
589int
590bgp_listen_limit_unset (struct bgp *bgp)
591{
592 if (! bgp)
593 return -1;
594
595 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
596
597 return 0;
598}
599
3f9c7369
DS
600struct peer_af *
601peer_af_create (struct peer *peer, afi_t afi, safi_t safi)
602{
603 struct peer_af *af;
604 int afid;
605
606 if (!peer)
607 return NULL;
608
609 afid = afindex(afi, safi);
610 if (afid >= BGP_AF_MAX)
611 return NULL;
612
613 assert(peer->peer_af_array[afid] == NULL);
614
615 /* Allocate new peer af */
616 af = XCALLOC (MTYPE_BGP_PEER_AF, sizeof (struct peer_af));
617 peer->peer_af_array[afid] = af;
618 af->afi = afi;
619 af->safi = safi;
620 af->afid = afid;
621 af->peer = peer;
622
623 //update_group_adjust_peer(af);
624 return af;
625}
626
627struct peer_af *
628peer_af_find (struct peer *peer, afi_t afi, safi_t safi)
629{
630 int afid;
631
632 if (!peer)
633 return NULL;
634
635 afid = afindex(afi, safi);
636 if (afid >= BGP_AF_MAX)
637 return NULL;
638
639 return peer->peer_af_array[afid];
640}
641
642int
643peer_af_delete (struct peer *peer, afi_t afi, safi_t safi)
644{
645 struct peer_af *af;
646 int afid;
647
648 if (!peer)
649 return -1;
650
651 afid = afindex(afi, safi);
652 if (afid >= BGP_AF_MAX)
653 return -1;
654
655 af = peer->peer_af_array[afid];
656 if (!af)
657 return -1;
658
659 bgp_stop_announce_route_timer (af);
660
661 if (PAF_SUBGRP(af))
662 {
663 if (BGP_DEBUG (update_groups, UPDATE_GROUPS))
ffd0c037 664 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " remove peer %s",
3f9c7369
DS
665 af->subgroup->update_group->id, af->subgroup->id, peer->host);
666 }
667
668 update_subgroup_remove_peer (af->subgroup, af);
669
670 peer->peer_af_array[afid] = NULL;
671 XFREE(MTYPE_BGP_PEER_AF, af);
672 return 0;
673}
674
675
fee0f4c6 676/* If peer is RSERVER_CLIENT in at least one address family and is not member
677 of a peer_group for that family, return 1.
678 Used to check wether the peer is included in list bgp->rsclient. */
679int
680peer_rsclient_active (struct peer *peer)
681{
682 int i;
683 int j;
684
685 for (i=AFI_IP; i < AFI_MAX; i++)
686 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
687 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
688 && ! peer->af_group[i][j])
689 return 1;
690 return 0;
691}
692
eb821189 693/* Peer comparison function for sorting. */
16286195 694int
718e3744 695peer_cmp (struct peer *p1, struct peer *p2)
696{
eb821189 697 return sockunion_cmp (&p1->su, &p2->su);
718e3744 698}
699
700int
701peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
702{
703 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
704}
705
706/* Reset all address family specific configuration. */
707static void
708peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
709{
710 int i;
711 struct bgp_filter *filter;
712 char orf_name[BUFSIZ];
713
714 filter = &peer->filter[afi][safi];
715
716 /* Clear neighbor filter and route-map */
717 for (i = FILTER_IN; i < FILTER_MAX; i++)
718 {
719 if (filter->dlist[i].name)
720 {
721 free (filter->dlist[i].name);
722 filter->dlist[i].name = NULL;
723 }
724 if (filter->plist[i].name)
725 {
726 free (filter->plist[i].name);
727 filter->plist[i].name = NULL;
728 }
729 if (filter->aslist[i].name)
730 {
731 free (filter->aslist[i].name);
732 filter->aslist[i].name = NULL;
733 }
fee0f4c6 734 }
735 for (i = RMAP_IN; i < RMAP_MAX; i++)
736 {
718e3744 737 if (filter->map[i].name)
738 {
739 free (filter->map[i].name);
740 filter->map[i].name = NULL;
741 }
742 }
743
744 /* Clear unsuppress map. */
745 if (filter->usmap.name)
746 free (filter->usmap.name);
747 filter->usmap.name = NULL;
748 filter->usmap.map = NULL;
749
750 /* Clear neighbor's all address family flags. */
751 peer->af_flags[afi][safi] = 0;
752
753 /* Clear neighbor's all address family sflags. */
754 peer->af_sflags[afi][safi] = 0;
755
756 /* Clear neighbor's all address family capabilities. */
757 peer->af_cap[afi][safi] = 0;
758
759 /* Clear ORF info */
760 peer->orf_plist[afi][safi] = NULL;
761 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
762 prefix_bgp_orf_remove_all (orf_name);
763
764 /* Set default neighbor send-community. */
765 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
766 {
767 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
768 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
769 }
770
771 /* Clear neighbor default_originate_rmap */
772 if (peer->default_rmap[afi][safi].name)
773 free (peer->default_rmap[afi][safi].name);
774 peer->default_rmap[afi][safi].name = NULL;
775 peer->default_rmap[afi][safi].map = NULL;
776
777 /* Clear neighbor maximum-prefix */
778 peer->pmax[afi][safi] = 0;
e0701b79 779 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
718e3744 780}
781
782/* peer global config reset */
94f2b392 783static void
718e3744 784peer_global_config_reset (struct peer *peer)
785{
8ffedcea
DS
786
787 int v6only;
788
718e3744 789 peer->weight = 0;
790 peer->change_local_as = 0;
791 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
792 if (peer->update_source)
793 {
794 sockunion_free (peer->update_source);
795 peer->update_source = NULL;
796 }
797 if (peer->update_if)
798 {
799 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
800 peer->update_if = NULL;
801 }
802
803 if (peer_sort (peer) == BGP_PEER_IBGP)
804 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
805 else
806 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
807
8ffedcea
DS
808 /* This is a per-peer specific flag and so we must preserve it */
809 v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
810
718e3744 811 peer->flags = 0;
8ffedcea
DS
812
813 if (v6only)
814 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
815
718e3744 816 peer->config = 0;
817 peer->holdtime = 0;
818 peer->keepalive = 0;
819 peer->connect = 0;
820 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
821a359a
DS
821
822 /* Reset some other configs back to defaults. */
823 peer->v_start = BGP_INIT_START_TIMER;
824 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
825 peer->password = NULL;
826 peer->local_id = peer->bgp->router_id;
827 peer->v_holdtime = peer->bgp->default_holdtime;
828 peer->v_keepalive = peer->bgp->default_keepalive;
829
7f342629
DS
830 bfd_info_free(&(peer->bfd_info));
831
821a359a
DS
832 /* Set back the CONFIG_NODE flag. */
833 SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 834}
835
6d85b15b
JBD
836/* Check peer's AS number and determines if this peer is IBGP or EBGP */
837static bgp_peer_sort_t
838peer_calc_sort (struct peer *peer)
718e3744 839{
840 struct bgp *bgp;
841
842 bgp = peer->bgp;
843
844 /* Peer-group */
845 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
846 {
66b199b2
DS
847 if (peer->as_type == AS_INTERNAL)
848 return BGP_PEER_IBGP;
849
850 else if (peer->as_type == AS_EXTERNAL)
851 return BGP_PEER_EBGP;
852
853 else if (peer->as_type == AS_SPECIFIED && peer->as)
718e3744 854 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
66b199b2 855
718e3744 856 else
857 {
858 struct peer *peer1;
859 peer1 = listnode_head (peer->group->peer);
66b199b2 860
718e3744 861 if (peer1)
66b199b2 862 return peer1->sort;
718e3744 863 }
864 return BGP_PEER_INTERNAL;
865 }
866
867 /* Normal peer */
868 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
869 {
870 if (peer->local_as == 0)
871 return BGP_PEER_INTERNAL;
872
873 if (peer->local_as == peer->as)
874 {
66b199b2
DS
875 if (bgp->as == bgp->confed_id)
876 {
877 if (peer->local_as == bgp->as)
878 return BGP_PEER_IBGP;
879 else
880 return BGP_PEER_EBGP;
881 }
882 else
883 {
884 if (peer->local_as == bgp->confed_id)
885 return BGP_PEER_EBGP;
886 else
887 return BGP_PEER_IBGP;
888 }
718e3744 889 }
890
891 if (bgp_confederation_peers_check (bgp, peer->as))
892 return BGP_PEER_CONFED;
893
894 return BGP_PEER_EBGP;
895 }
896 else
897 {
0299c004
DS
898 if (peer->as_type != AS_SPECIFIED)
899 return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP);
900
718e3744 901 return (peer->local_as == 0
902 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
903 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
904 }
905}
906
6d85b15b
JBD
907/* Calculate and cache the peer "sort" */
908bgp_peer_sort_t
909peer_sort (struct peer *peer)
910{
911 peer->sort = peer_calc_sort (peer);
912 return peer->sort;
913}
914
f63f06da 915static void
200df115 916peer_free (struct peer *peer)
917{
ca058a30 918 assert (peer->status == Deleted);
0088b5dc
SH
919
920 bgp_unlock(peer->bgp);
921
ca058a30
PJ
922 /* this /ought/ to have been done already through bgp_stop earlier,
923 * but just to be sure..
924 */
925 bgp_timer_set (peer);
926 BGP_READ_OFF (peer->t_read);
927 BGP_WRITE_OFF (peer->t_write);
9fde6624 928 BGP_EVENT_FLUSH (peer);
ca058a30 929
9a233a02
DS
930 /* Free connected nexthop, if present */
931 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
932 !peer_dynamic_neighbor (peer))
933 bgp_delete_connected_nexthop (family2afi(peer->su.sa.sa_family), peer);
934
200df115 935 if (peer->desc)
936 XFREE (MTYPE_PEER_DESC, peer->desc);
937
938 /* Free allocated host character. */
939 if (peer->host)
940 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
941
942 /* Update source configuration. */
943 if (peer->update_source)
944 sockunion_free (peer->update_source);
945
946 if (peer->update_if)
947 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
a625ca3c
PJ
948
949 if (peer->clear_node_queue)
950 work_queue_free (peer->clear_node_queue);
951
ca058a30 952 bgp_sync_delete (peer);
a80beece
DS
953
954 if (peer->conf_if)
955 XFREE (MTYPE_PEER_CONF_IF, peer->conf_if);
956
7f342629 957 bfd_info_free(&(peer->bfd_info));
c43ed2e4 958
200df115 959 memset (peer, 0, sizeof (struct peer));
960
961 XFREE (MTYPE_BGP_PEER, peer);
962}
963
964/* increase reference count on a struct peer */
965struct peer *
28066f4b 966peer_lock_with_caller (const char *name, struct peer *peer)
200df115 967{
968 assert (peer && (peer->lock >= 0));
28066f4b
DS
969
970#if 0
971 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
972#endif
ca058a30 973
200df115 974 peer->lock++;
975
976 return peer;
977}
978
979/* decrease reference count on a struct peer
980 * struct peer is freed and NULL returned if last reference
981 */
982struct peer *
28066f4b 983peer_unlock_with_caller (const char *name, struct peer *peer)
200df115 984{
985 assert (peer && (peer->lock > 0));
28066f4b
DS
986
987#if 0
988 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
989#endif
200df115 990
991 peer->lock--;
992
993 if (peer->lock == 0)
994 {
200df115 995 peer_free (peer);
996 return NULL;
997 }
998
200df115 999 return peer;
1000}
1ff9a340 1001
200df115 1002/* Allocate new peer object, implicitely locked. */
718e3744 1003static struct peer *
6f58544d 1004peer_new (struct bgp *bgp)
718e3744 1005{
1006 afi_t afi;
1007 safi_t safi;
1008 struct peer *peer;
1009 struct servent *sp;
6f58544d
PJ
1010
1011 /* bgp argument is absolutely required */
1012 assert (bgp);
1013 if (!bgp)
1014 return NULL;
1015
718e3744 1016 /* Allocate new peer. */
ca058a30 1017 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
718e3744 1018
1019 /* Set default value. */
eb821189 1020 peer->fd = -1;
718e3744 1021 peer->v_start = BGP_INIT_START_TIMER;
1022 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1023 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
1024 peer->status = Idle;
1025 peer->ostatus = Idle;
6403814c 1026 peer->cur_event = peer->last_event = peer->last_major_event = 0;
6f58544d 1027 peer->bgp = bgp;
ca058a30 1028 peer = peer_lock (peer); /* initial reference */
0088b5dc 1029 bgp_lock (bgp);
1ff9a340
DS
1030 peer->weight = 0;
1031 peer->password = NULL;
718e3744 1032
1033 /* Set default flags. */
1034 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1035 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1036 {
1037 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
1038 {
1039 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
1040 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
1041 }
1042 peer->orf_plist[afi][safi] = NULL;
1043 }
1044 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1045
1046 /* Create buffers. */
1047 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
1048 peer->obuf = stream_fifo_new ();
0a91ff55
DS
1049
1050 /* We use a larger buffer for peer->work in the event that:
1051 * - We RX a BGP_UPDATE where the attributes alone are just
1052 * under BGP_MAX_PACKET_SIZE
1053 * - The user configures an outbound route-map that does many as-path
1054 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
1055 * args in a route-map so there is a finite limit on how large they can
1056 * make the attributes.
1057 *
1058 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
1059 * checking for every single attribute as we construct an UPDATE.
1060 */
1061 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
8c71e481 1062 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
718e3744 1063
1ff9a340 1064
718e3744 1065 bgp_sync_init (peer);
1066
1067 /* Get service port number. */
1068 sp = getservbyname ("bgp", "tcp");
1069 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
1070
1071 return peer;
1072}
1073
1ff9a340
DS
1074/*
1075 * This function is invoked when a duplicate peer structure associated with
1076 * a neighbor is being deleted. If this about-to-be-deleted structure is
1077 * the one with all the config, then we have to copy over the info.
1078 */
1079void
1080peer_xfer_config (struct peer *peer_dst, struct peer *peer_src)
1081{
3f9c7369 1082 struct peer_af *paf;
1ff9a340
DS
1083 afi_t afi;
1084 safi_t safi;
3f9c7369 1085 int afindex;
1ff9a340
DS
1086
1087 assert(peer_src);
1088 assert(peer_dst);
1089
1090 /* The following function is used by both peer group config copy to
1091 * individual peer and when we transfer config
1092 */
1093 if (peer_src->change_local_as)
1094 peer_dst->change_local_as = peer_src->change_local_as;
1095
1096 /* peer flags apply */
1097 peer_dst->flags = peer_src->flags;
1098 peer_dst->cap = peer_src->cap;
1099 peer_dst->config = peer_src->config;
1100
1101 peer_dst->local_as = peer_src->local_as;
1102 peer_dst->ifindex = peer_src->ifindex;
1103 peer_dst->port = peer_src->port;
1104 peer_sort(peer_dst);
1105 peer_dst->rmap_type = peer_src->rmap_type;
1106
1107 /* Timers */
1108 peer_dst->holdtime = peer_src->holdtime;
1109 peer_dst->keepalive = peer_src->keepalive;
1110 peer_dst->connect = peer_src->connect;
1111 peer_dst->v_holdtime = peer_src->v_holdtime;
1112 peer_dst->v_keepalive = peer_src->v_keepalive;
1113 peer_dst->v_asorig = peer_src->v_asorig;
1114 peer_dst->routeadv = peer_src->routeadv;
1115 peer_dst->v_routeadv = peer_src->v_routeadv;
1116
1117 /* password apply */
1118 if (peer_src->password && !peer_dst->password)
1119 peer_dst->password = XSTRDUP (MTYPE_PEER_PASSWORD, peer_src->password);
1120
1ff9a340
DS
1121 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1122 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1123 {
1124 peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
1125 peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
1126 peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi];
1127 }
1128
3f9c7369
DS
1129 PEERAF_FOREACH(peer_src, paf, afindex)
1130 peer_af_create(peer_dst, paf->afi, paf->safi);
1131
1ff9a340
DS
1132 /* update-source apply */
1133 if (peer_src->update_source)
1134 {
1135 if (peer_dst->update_source)
1136 sockunion_free (peer_dst->update_source);
1137 if (peer_dst->update_if)
1138 {
1139 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
1140 peer_dst->update_if = NULL;
1141 }
1142 peer_dst->update_source = sockunion_dup (peer_src->update_source);
1143 }
1144 else if (peer_src->update_if)
1145 {
1146 if (peer_dst->update_if)
1147 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
1148 if (peer_dst->update_source)
1149 {
1150 sockunion_free (peer_dst->update_source);
1151 peer_dst->update_source = NULL;
1152 }
1153 peer_dst->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if);
1154 }
1155
1156 if (peer_src->ifname)
1157 {
1158 if (peer_dst->ifname)
1159 free(peer_dst->ifname);
1160
1161 peer_dst->ifname = strdup(peer_src->ifname);
1162 }
1163}
1164
a80beece
DS
1165/*
1166 * Set or reset the peer address socketunion structure based on the
1167 * learnt peer address. Currently via the source address of the
1168 * ipv6 ND router-advertisement.
1169 */
1170void
1171bgp_peer_conf_if_to_su_update (struct peer *peer)
1172{
1173 struct interface *ifp;
8ffedcea
DS
1174 struct nbr_connected *ifc_nbr;
1175 struct connected *ifc;
1176 struct prefix p;
1177 u_int32_t s_addr;
1178 struct listnode *node;
a80beece
DS
1179
1180 if (!peer->conf_if)
1181 return;
1182
88177fe3 1183 if ((ifp = if_lookup_by_name(peer->conf_if)))
a80beece 1184 {
8ffedcea
DS
1185 /* if multiple IP addresses assigned to link, we pick the first */
1186 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
1187 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
1188 if (ifc->address && (ifc->address->family == AF_INET))
1189 {
1190 /* Try IPv4 connection first, if present */
1191 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
1192 /* We can determine peer's IP address if prefixlen is 30/31 */
1193 if (p.prefixlen == 30)
1194 {
1195 peer->su.sa.sa_family = AF_INET;
1196 s_addr = ntohl(p.u.prefix4.s_addr);
1197 if (s_addr % 4 == 1)
1198 peer->su.sin.sin_addr.s_addr = htonl(s_addr+1);
1199 else if (s_addr % 4 == 2)
1200 peer->su.sin.sin_addr.s_addr = htonl(s_addr-1);
1201#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1202 peer->su->sin.sin_len = sizeof(struct sockaddr_in);
1203#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1204 return;
1205 }
1206 else if (p.prefixlen == 31)
1207 {
1208 peer->su.sa.sa_family = AF_INET;
1209 s_addr = ntohl(p.u.prefix4.s_addr);
1210 if (s_addr % 2 == 0)
1211 peer->su.sin.sin_addr.s_addr = htonl(s_addr+1);
1212 else
1213 peer->su.sin.sin_addr.s_addr = htonl(s_addr-1);
1214#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1215 peer->su->sin.sin_len = sizeof(struct sockaddr_in);
1216#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
1217 return;
1218 }
1219 else
1220 zlog_warn("%s neighbor interface with IPv4 numbered links used without /30 or /31",
1221 peer->conf_if);
1222 }
1223
1224 if (ifp->nbr_connected &&
1225 (ifc_nbr = listnode_head(ifp->nbr_connected)))
1226 {
1227 peer->su.sa.sa_family = AF_INET6;
1228 memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix,
1229 sizeof (struct in6_addr));
a80beece 1230#ifdef SIN6_LEN
8ffedcea 1231 peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6);
a80beece 1232#endif
8ffedcea
DS
1233 peer->su.sin6.sin6_scope_id = ifp->ifindex;
1234
1235 return;
1236 }
a80beece 1237 }
8ffedcea
DS
1238 /* This works as an indication of unresolved peer address
1239 on a BGP interface*/
1240 peer->su.sa.sa_family = AF_UNSPEC;
1241 memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr));
a80beece
DS
1242}
1243
718e3744 1244/* Create new BGP peer. */
1ff9a340 1245struct peer *
a80beece 1246peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
0299c004 1247 as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi)
718e3744 1248{
1249 int active;
1250 struct peer *peer;
1251 char buf[SU_ADDRSTRLEN];
1252
6f58544d 1253 peer = peer_new (bgp);
a80beece
DS
1254 if (conf_if)
1255 {
1256 peer->conf_if = XSTRDUP (MTYPE_PEER_CONF_IF, conf_if);
1257 bgp_peer_conf_if_to_su_update(peer);
1258 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, conf_if);
1259 }
1260 else if (su)
1261 {
1262 peer->su = *su;
1263 sockunion2str (su, buf, SU_ADDRSTRLEN);
1264 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
1265 }
718e3744 1266 peer->local_as = local_as;
1267 peer->as = remote_as;
0299c004 1268 peer->as_type = as_type;
718e3744 1269 peer->local_id = bgp->router_id;
1270 peer->v_holdtime = bgp->default_holdtime;
1271 peer->v_keepalive = bgp->default_keepalive;
1272 if (peer_sort (peer) == BGP_PEER_IBGP)
1273 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1274 else
1275 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
28066f4b 1276
200df115 1277 peer = peer_lock (peer); /* bgp peer list reference */
718e3744 1278 listnode_add_sort (bgp->peer, peer);
1279
1280 active = peer_active (peer);
1281
65957886
SH
1282 /* Last read and reset time set */
1283 peer->readtime = peer->resettime = bgp_clock ();
848973c7 1284
718e3744 1285 /* Default TTL set. */
6d85b15b 1286 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
718e3744 1287
1ff9a340
DS
1288 SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
1289
3f9c7369
DS
1290 if (afi && safi)
1291 {
1292 peer->afc[afi][safi] = 1;
1293 if (peer_af_create(peer, afi, safi) == NULL)
1294 {
1295 zlog_err("couldn't create af structure for peer %s", peer->host);
1296 }
1297 }
1298
718e3744 1299 /* Set up peer's events and timers. */
1300 if (! active && peer_active (peer))
1301 bgp_timer_set (peer);
1302
1303 return peer;
1304}
1305
a80beece
DS
1306struct peer *
1307peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi,
8ffedcea 1308 safi_t safi, int v6only)
a80beece
DS
1309{
1310 struct peer *peer;
1311
1312 peer = peer_lookup_by_conf_if (bgp, conf_if);
1313 if (!peer)
1314 {
1315 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1316 && afi == AFI_IP && safi == SAFI_UNICAST)
0299c004 1317 peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, 0, 0);
a80beece 1318 else
0299c004 1319 peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, afi, safi);
a80beece 1320
8ffedcea
DS
1321 if (peer && v6only)
1322 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
1323 }
1324 else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) ||
1325 (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)))
1326 {
1327 if (v6only)
1328 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
1329 else
1330 UNSET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
1331
1332 /* v6only flag changed. Reset bgp seesion */
1333 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
1334 {
1335 peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
1336 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1337 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1338 }
1339 else
1340 bgp_session_reset(peer);
a80beece
DS
1341 }
1342
1343 return peer;
1344}
1345
eb821189 1346/* Make accept BGP peer. Called from bgp_accept (). */
1347struct peer *
1348peer_create_accept (struct bgp *bgp)
1349{
1350 struct peer *peer;
1351
6f58544d 1352 peer = peer_new (bgp);
1ff9a340 1353
200df115 1354 peer = peer_lock (peer); /* bgp peer list reference */
eb821189 1355 listnode_add_sort (bgp->peer, peer);
1356
1357 return peer;
1358}
1359
718e3744 1360/* Change peer's AS number. */
a80beece 1361void
0299c004 1362peer_as_change (struct peer *peer, as_t as, int as_specified)
718e3744 1363{
6d85b15b 1364 bgp_peer_sort_t type;
966f821c 1365 struct peer *conf;
718e3744 1366
1367 /* Stop peer. */
1368 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1369 {
6aa136f1 1370 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 1371 {
1372 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
1373 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1374 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1375 }
718e3744 1376 else
1ff9a340 1377 bgp_session_reset(peer);
718e3744 1378 }
1379 type = peer_sort (peer);
1380 peer->as = as;
0299c004 1381 peer->as_type = as_specified;
718e3744 1382
848973c7 1383 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
1384 && ! bgp_confederation_peers_check (peer->bgp, as)
1385 && peer->bgp->as != as)
1386 peer->local_as = peer->bgp->confed_id;
1387 else
1388 peer->local_as = peer->bgp->as;
1389
718e3744 1390 /* Advertisement-interval reset */
966f821c
DS
1391 conf = NULL;
1392 if (peer->group)
1393 conf = peer->group->conf;
1394
1395 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
ffd0c037 1396 {
966f821c 1397 peer->v_routeadv = conf->routeadv;
ffd0c037 1398 }
d973c4f0
DS
1399 /* Only go back to the default advertisement-interval if the user had not
1400 * already configured it */
1401 else if (!CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
ffd0c037
DS
1402 {
1403 if (peer_sort (peer) == BGP_PEER_IBGP)
1404 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1405 else
1406 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1407 }
718e3744 1408 /* TTL reset */
1409 if (peer_sort (peer) == BGP_PEER_IBGP)
1410 peer->ttl = 255;
1411 else if (type == BGP_PEER_IBGP)
1412 peer->ttl = 1;
1413
1414 /* reflector-client reset */
1415 if (peer_sort (peer) != BGP_PEER_IBGP)
1416 {
1417 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
1418 PEER_FLAG_REFLECTOR_CLIENT);
1419 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1420 PEER_FLAG_REFLECTOR_CLIENT);
1421 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1422 PEER_FLAG_REFLECTOR_CLIENT);
1423 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1424 PEER_FLAG_REFLECTOR_CLIENT);
1425 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1426 PEER_FLAG_REFLECTOR_CLIENT);
1427 }
1428
1429 /* local-as reset */
1430 if (peer_sort (peer) != BGP_PEER_EBGP)
1431 {
1432 peer->change_local_as = 0;
1433 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 1434 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 1435 }
1436}
1437
1438/* If peer does not exist, create new one. If peer already exists,
1439 set AS number to the peer. */
1440int
0299c004
DS
1441peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if,
1442 as_t *as, int as_type, afi_t afi, safi_t safi)
718e3744 1443{
1444 struct peer *peer;
1445 as_t local_as;
1446
a80beece
DS
1447 if (conf_if)
1448 peer = peer_lookup_by_conf_if (bgp, conf_if);
1449 else
1450 peer = peer_lookup (bgp, su);
718e3744 1451
1452 if (peer)
1453 {
f14e6fdb
DS
1454 /* Not allowed for a dynamic peer. */
1455 if (peer_dynamic_neighbor (peer))
1456 {
1457 *as = peer->as;
1458 return BGP_ERR_INVALID_FOR_DYNAMIC_PEER;
1459 }
1460
718e3744 1461 /* When this peer is a member of peer-group. */
1462 if (peer->group)
1463 {
1464 if (peer->group->conf->as)
1465 {
1466 /* Return peer group's AS number. */
1467 *as = peer->group->conf->as;
1468 return BGP_ERR_PEER_GROUP_MEMBER;
1469 }
1470 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1471 {
0299c004 1472 if ((as_type != AS_INTERNAL) && (bgp->as != *as))
718e3744 1473 {
1474 *as = peer->as;
1475 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1476 }
1477 }
1478 else
1479 {
0299c004 1480 if ((as_type != AS_EXTERNAL) && (bgp->as == *as))
718e3744 1481 {
1482 *as = peer->as;
1483 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1484 }
1485 }
1486 }
1487
1488 /* Existing peer's AS number change. */
1489 if (peer->as != *as)
0299c004 1490 peer_as_change (peer, *as, as_type);
718e3744 1491 }
1492 else
1493 {
a80beece
DS
1494 if (conf_if)
1495 return BGP_ERR_NO_INTERFACE_CONFIG;
718e3744 1496
1497 /* If the peer is not part of our confederation, and its not an
1498 iBGP peer then spoof the source AS */
1499 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1500 && ! bgp_confederation_peers_check (bgp, *as)
1501 && bgp->as != *as)
1502 local_as = bgp->confed_id;
1503 else
1504 local_as = bgp->as;
1505
1506 /* If this is IPv4 unicast configuration and "no bgp default
1507 ipv4-unicast" is specified. */
1508
1509 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1510 && afi == AFI_IP && safi == SAFI_UNICAST)
0299c004 1511 peer = peer_create (su, conf_if, bgp, local_as, *as, as_type, 0, 0);
718e3744 1512 else
0299c004 1513 peer = peer_create (su, conf_if, bgp, local_as, *as, as_type, afi, safi);
718e3744 1514 }
1515
1516 return 0;
1517}
1518
1519/* Activate the peer or peer group for specified AFI and SAFI. */
1520int
1521peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1522{
1523 int active;
1524
1525 if (peer->afc[afi][safi])
1526 return 0;
1527
1528 /* Activate the address family configuration. */
1529 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1530 peer->afc[afi][safi] = 1;
1531 else
1532 {
1533 active = peer_active (peer);
1534
1535 peer->afc[afi][safi] = 1;
1536
3f9c7369
DS
1537 if (peer_af_create(peer, afi, safi) == NULL)
1538 {
1539 zlog_err("couldn't create af structure for peer %s", peer->host);
1540 }
1541
718e3744 1542 if (! active && peer_active (peer))
1543 bgp_timer_set (peer);
1544 else
1545 {
1546 if (peer->status == Established)
1547 {
1548 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1549 {
1550 peer->afc_adv[afi][safi] = 1;
1551 bgp_capability_send (peer, afi, safi,
1552 CAPABILITY_CODE_MP,
1553 CAPABILITY_ACTION_SET);
1554 if (peer->afc_recv[afi][safi])
1555 {
1556 peer->afc_nego[afi][safi] = 1;
1557 bgp_announce_route (peer, afi, safi);
1558 }
1559 }
1560 else
e0701b79 1561 {
1562 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1563 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1564 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1565 }
718e3744 1566 }
1567 }
1568 }
1569 return 0;
1570}
1571
1572int
1573peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1574{
1575 struct peer_group *group;
1576 struct peer *peer1;
1eb8ef25 1577 struct listnode *node, *nnode;
718e3744 1578
1579 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1580 {
1581 group = peer->group;
1582
1eb8ef25 1583 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
718e3744 1584 {
1585 if (peer1->af_group[afi][safi])
1586 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1587 }
1588 }
1589 else
1590 {
1591 if (peer->af_group[afi][safi])
1592 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1593 }
1594
1595 if (! peer->afc[afi][safi])
1596 return 0;
1597
1598 /* De-activate the address family configuration. */
1599 peer->afc[afi][safi] = 0;
1600 peer_af_flag_reset (peer, afi, safi);
3f9c7369
DS
1601 if (peer_af_delete(peer, afi, safi) != 0)
1602 {
1603 zlog_err("couldn't delete af structure for peer %s", peer->host);
1604 }
718e3744 1605
1606 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1607 {
1608 if (peer->status == Established)
1609 {
1610 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1611 {
1612 peer->afc_adv[afi][safi] = 0;
1613 peer->afc_nego[afi][safi] = 0;
1614
1615 if (peer_active_nego (peer))
1616 {
1617 bgp_capability_send (peer, afi, safi,
1618 CAPABILITY_CODE_MP,
1619 CAPABILITY_ACTION_UNSET);
228da428 1620 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
718e3744 1621 peer->pcount[afi][safi] = 0;
1622 }
1623 else
e0701b79 1624 {
1625 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1626 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1627 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1628 }
718e3744 1629 }
1630 else
e0701b79 1631 {
1632 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1633 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1634 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1635 }
718e3744 1636 }
1637 }
1638 return 0;
1639}
1640
da88ea82 1641static void
93406d87 1642peer_nsf_stop (struct peer *peer)
1643{
1644 afi_t afi;
1645 safi_t safi;
1646
1647 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1648 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1649
1650 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
0a28130d 1651 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
93406d87 1652 peer->nsf[afi][safi] = 0;
1653
1654 if (peer->t_gr_restart)
1655 {
1656 BGP_TIMER_OFF (peer->t_gr_restart);
16286195 1657 if (bgp_debug_neighbor_events(peer))
93406d87 1658 zlog_debug ("%s graceful restart timer stopped", peer->host);
1659 }
1660 if (peer->t_gr_stale)
1661 {
1662 BGP_TIMER_OFF (peer->t_gr_stale);
16286195 1663 if (bgp_debug_neighbor_events(peer))
93406d87 1664 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1665 }
1666 bgp_clear_route_all (peer);
1667}
1668
ca058a30
PJ
1669/* Delete peer from confguration.
1670 *
1671 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1672 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1673 *
1674 * This function /should/ take care to be idempotent, to guard against
1675 * it being called multiple times through stray events that come in
1676 * that happen to result in this function being called again. That
1677 * said, getting here for a "Deleted" peer is a bug in the neighbour
1678 * FSM.
1679 */
718e3744 1680int
1681peer_delete (struct peer *peer)
1682{
1683 int i;
1684 afi_t afi;
1685 safi_t safi;
1686 struct bgp *bgp;
1687 struct bgp_filter *filter;
228da428 1688 struct listnode *pn;
019cbf70 1689 int accept_peer;
718e3744 1690
ca058a30 1691 assert (peer->status != Deleted);
1ff9a340 1692
718e3744 1693 bgp = peer->bgp;
019cbf70 1694 accept_peer = CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
718e3744 1695
93406d87 1696 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1697 peer_nsf_stop (peer);
1698
1ff9a340
DS
1699 SET_FLAG(peer->flags, PEER_FLAG_DELETE);
1700
228da428 1701 /* If this peer belongs to peer group, clear up the
718e3744 1702 relationship. */
1703 if (peer->group)
1704 {
f14e6fdb
DS
1705 if (peer_dynamic_neighbor(peer))
1706 peer_drop_dynamic_neighbor(peer);
1707
ca058a30
PJ
1708 if ((pn = listnode_lookup (peer->group->peer, peer)))
1709 {
1710 peer = peer_unlock (peer); /* group->peer list reference */
1711 list_delete_node (peer->group->peer, pn);
1712 }
718e3744 1713 peer->group = NULL;
1714 }
200df115 1715
718e3744 1716 /* Withdraw all information from routing table. We can not use
200df115 1717 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1718 * executed after peer structure is deleted.
1719 */
e0701b79 1720 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
718e3744 1721 bgp_stop (peer);
1ff9a340
DS
1722 UNSET_FLAG(peer->flags, PEER_FLAG_DELETE);
1723
1724 if (peer->doppelganger)
1725 peer->doppelganger->doppelganger = NULL;
1726 peer->doppelganger = NULL;
1727
1728 UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
ca058a30 1729 bgp_fsm_change_status (peer, Deleted);
0df7c91f
PJ
1730
1731 /* Password configuration */
1732 if (peer->password)
1733 {
1734 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1735 peer->password = NULL;
1736
019cbf70
DS
1737 if (!accept_peer &&
1738 ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
0df7c91f
PJ
1739 bgp_md5_set (peer);
1740 }
1741
ca058a30 1742 bgp_timer_set (peer); /* stops all timers for Deleted */
1ff9a340 1743
718e3744 1744 /* Delete from all peer list. */
228da428
CC
1745 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1746 && (pn = listnode_lookup (bgp->peer, peer)))
fee0f4c6 1747 {
228da428
CC
1748 peer_unlock (peer); /* bgp peer list reference */
1749 list_delete_node (bgp->peer, pn);
1750 }
200df115 1751
228da428
CC
1752 if (peer_rsclient_active (peer)
1753 && (pn = listnode_lookup (bgp->rsclient, peer)))
1754 {
1755 peer_unlock (peer); /* rsclient list reference */
1756 list_delete_node (bgp->rsclient, pn);
1757
1ff9a340
DS
1758 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1759 {
1760 /* Clear our own rsclient ribs. */
1761 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1762 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1763 if (CHECK_FLAG(peer->af_flags[afi][safi],
1764 PEER_FLAG_RSERVER_CLIENT))
1765 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
1766 }
fee0f4c6 1767 }
1768
1769 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1770 member of a peer_group. */
1771 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1772 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1773 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
b608d5b5 1774 bgp_table_finish (&peer->rib[afi][safi]);
718e3744 1775
200df115 1776 /* Buffers. */
718e3744 1777 if (peer->ibuf)
1778 stream_free (peer->ibuf);
718e3744 1779 if (peer->obuf)
1780 stream_fifo_free (peer->obuf);
718e3744 1781 if (peer->work)
1782 stream_free (peer->work);
8c71e481
PM
1783 if (peer->scratch)
1784 stream_free(peer->scratch);
18937400 1785 peer->obuf = NULL;
8c71e481 1786 peer->work = peer->scratch = peer->ibuf = NULL;
18937400 1787
718e3744 1788 /* Local and remote addresses. */
1789 if (peer->su_local)
22db9dec 1790 sockunion_free (peer->su_local);
718e3744 1791 if (peer->su_remote)
22db9dec 1792 sockunion_free (peer->su_remote);
18937400 1793 peer->su_local = peer->su_remote = NULL;
200df115 1794
718e3744 1795 /* Free filter related memory. */
1796 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1797 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1798 {
1799 filter = &peer->filter[afi][safi];
1800
1801 for (i = FILTER_IN; i < FILTER_MAX; i++)
1802 {
1803 if (filter->dlist[i].name)
1804 free (filter->dlist[i].name);
1805 if (filter->plist[i].name)
1806 free (filter->plist[i].name);
1807 if (filter->aslist[i].name)
1808 free (filter->aslist[i].name);
200df115 1809
1810 filter->dlist[i].name = NULL;
1811 filter->plist[i].name = NULL;
1812 filter->aslist[i].name = NULL;
1813 }
1814 for (i = RMAP_IN; i < RMAP_MAX; i++)
1815 {
718e3744 1816 if (filter->map[i].name)
1817 free (filter->map[i].name);
200df115 1818 filter->map[i].name = NULL;
718e3744 1819 }
1820
1821 if (filter->usmap.name)
1822 free (filter->usmap.name);
1823
1824 if (peer->default_rmap[afi][safi].name)
1825 free (peer->default_rmap[afi][safi].name);
200df115 1826
1827 filter->usmap.name = NULL;
1828 peer->default_rmap[afi][safi].name = NULL;
718e3744 1829 }
3f9c7369
DS
1830
1831 FOREACH_AFI_SAFI (afi, safi)
1832 peer_af_delete (peer, afi, safi);
200df115 1833 peer_unlock (peer); /* initial reference */
718e3744 1834
1835 return 0;
1836}
6b0655a2 1837
94f2b392 1838static int
718e3744 1839peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1840{
1841 return strcmp (g1->name, g2->name);
1842}
1843
718e3744 1844/* Peer group cofiguration. */
1845static struct peer_group *
66e5cd87 1846peer_group_new (void)
718e3744 1847{
1848 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1849 sizeof (struct peer_group));
1850}
1851
94f2b392 1852static void
718e3744 1853peer_group_free (struct peer_group *group)
1854{
1855 XFREE (MTYPE_PEER_GROUP, group);
1856}
1857
1858struct peer_group *
fd79ac91 1859peer_group_lookup (struct bgp *bgp, const char *name)
718e3744 1860{
1861 struct peer_group *group;
1eb8ef25 1862 struct listnode *node, *nnode;
718e3744 1863
1eb8ef25 1864 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 1865 {
1866 if (strcmp (group->name, name) == 0)
1867 return group;
1868 }
1869 return NULL;
1870}
1871
1872struct peer_group *
fd79ac91 1873peer_group_get (struct bgp *bgp, const char *name)
718e3744 1874{
1875 struct peer_group *group;
f14e6fdb 1876 afi_t afi;
718e3744 1877
1878 group = peer_group_lookup (bgp, name);
1879 if (group)
1880 return group;
1881
1882 group = peer_group_new ();
1883 group->bgp = bgp;
1884 group->name = strdup (name);
1885 group->peer = list_new ();
f14e6fdb
DS
1886 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1887 group->listen_range[afi] = list_new ();
6f58544d 1888 group->conf = peer_new (bgp);
718e3744 1889 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1890 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
228da428 1891 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
718e3744 1892 group->conf->group = group;
1893 group->conf->as = 0;
1894 group->conf->ttl = 1;
fa411a21 1895 group->conf->gtsm_hops = 0;
718e3744 1896 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1897 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1898 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1899 group->conf->keepalive = 0;
1900 group->conf->holdtime = 0;
1901 group->conf->connect = 0;
1902 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1903 listnode_add_sort (bgp->group, group);
1904
1905 return 0;
1906}
1907
94f2b392 1908static void
718e3744 1909peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1910 afi_t afi, safi_t safi)
1911{
1912 int in = FILTER_IN;
1913 int out = FILTER_OUT;
1914 struct peer *conf;
1915 struct bgp_filter *pfilter;
1916 struct bgp_filter *gfilter;
8ffedcea 1917 int v6only;
718e3744 1918
1919 conf = group->conf;
1920 pfilter = &peer->filter[afi][safi];
1921 gfilter = &conf->filter[afi][safi];
1922
1923 /* remote-as */
1924 if (conf->as)
1925 peer->as = conf->as;
1926
1927 /* remote-as */
1928 if (conf->change_local_as)
1929 peer->change_local_as = conf->change_local_as;
1930
1931 /* TTL */
1932 peer->ttl = conf->ttl;
1933
fa411a21
NH
1934 /* GTSM hops */
1935 peer->gtsm_hops = conf->gtsm_hops;
1936
718e3744 1937 /* Weight */
1938 peer->weight = conf->weight;
1939
8ffedcea
DS
1940 /* this flag is per-neighbor and so has to be preserved */
1941 v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
1942
718e3744 1943 /* peer flags apply */
1944 peer->flags = conf->flags;
8ffedcea
DS
1945
1946 if (v6only)
1947 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
1948
718e3744 1949 /* peer af_flags apply */
1950 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1951 /* peer config apply */
1952 peer->config = conf->config;
1953
1954 /* peer timers apply */
1955 peer->holdtime = conf->holdtime;
1956 peer->keepalive = conf->keepalive;
1957 peer->connect = conf->connect;
1958 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1959 peer->v_connect = conf->connect;
1960 else
1961 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1962
1963 /* advertisement-interval reset */
966f821c
DS
1964 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1965 peer->v_routeadv = conf->routeadv;
718e3744 1966 else
966f821c
DS
1967 if (peer_sort (peer) == BGP_PEER_IBGP)
1968 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1969 else
1970 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
718e3744 1971
0df7c91f 1972 /* password apply */
0e4303d3 1973 if (conf->password && !peer->password)
0df7c91f 1974 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
0df7c91f
PJ
1975
1976 bgp_md5_set (peer);
1977
718e3744 1978 /* maximum-prefix */
1979 peer->pmax[afi][safi] = conf->pmax[afi][safi];
e0701b79 1980 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
0a486e5f 1981 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
718e3744 1982
1983 /* allowas-in */
1984 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1985
fee0f4c6 1986 /* route-server-client */
1987 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1988 {
1989 /* Make peer's RIB point to group's RIB. */
1990 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1991
1992 /* Import policy. */
1993 if (pfilter->map[RMAP_IMPORT].name)
1994 free (pfilter->map[RMAP_IMPORT].name);
1995 if (gfilter->map[RMAP_IMPORT].name)
1996 {
1997 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1998 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1999 }
2000 else
2001 {
2002 pfilter->map[RMAP_IMPORT].name = NULL;
2003 pfilter->map[RMAP_IMPORT].map = NULL;
2004 }
2005
2006 /* Export policy. */
2007 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
2008 {
2009 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
2010 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
2011 }
2012 }
2013
718e3744 2014 /* default-originate route-map */
2015 if (conf->default_rmap[afi][safi].name)
2016 {
2017 if (peer->default_rmap[afi][safi].name)
2018 free (peer->default_rmap[afi][safi].name);
2019 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
2020 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
2021 }
2022
2023 /* update-source apply */
2024 if (conf->update_source)
2025 {
2026 if (peer->update_source)
2027 sockunion_free (peer->update_source);
2028 if (peer->update_if)
2029 {
2030 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2031 peer->update_if = NULL;
2032 }
2033 peer->update_source = sockunion_dup (conf->update_source);
2034 }
2035 else if (conf->update_if)
2036 {
2037 if (peer->update_if)
2038 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2039 if (peer->update_source)
2040 {
2041 sockunion_free (peer->update_source);
2042 peer->update_source = NULL;
2043 }
2044 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
2045 }
2046
2047 /* inbound filter apply */
2048 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
2049 {
2050 if (pfilter->dlist[in].name)
2051 free (pfilter->dlist[in].name);
2052 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
2053 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
2054 }
2055 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
2056 {
2057 if (pfilter->plist[in].name)
2058 free (pfilter->plist[in].name);
2059 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
2060 pfilter->plist[in].plist = gfilter->plist[in].plist;
2061 }
2062 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
2063 {
2064 if (pfilter->aslist[in].name)
2065 free (pfilter->aslist[in].name);
2066 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
2067 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
2068 }
fee0f4c6 2069 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
718e3744 2070 {
fee0f4c6 2071 if (pfilter->map[RMAP_IN].name)
2072 free (pfilter->map[RMAP_IN].name);
2073 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
2074 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
718e3744 2075 }
2076
2077 /* outbound filter apply */
2078 if (gfilter->dlist[out].name)
2079 {
2080 if (pfilter->dlist[out].name)
2081 free (pfilter->dlist[out].name);
2082 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
2083 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
2084 }
2085 else
2086 {
2087 if (pfilter->dlist[out].name)
2088 free (pfilter->dlist[out].name);
2089 pfilter->dlist[out].name = NULL;
2090 pfilter->dlist[out].alist = NULL;
2091 }
2092 if (gfilter->plist[out].name)
2093 {
2094 if (pfilter->plist[out].name)
2095 free (pfilter->plist[out].name);
2096 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
2097 pfilter->plist[out].plist = gfilter->plist[out].plist;
2098 }
2099 else
2100 {
2101 if (pfilter->plist[out].name)
2102 free (pfilter->plist[out].name);
2103 pfilter->plist[out].name = NULL;
2104 pfilter->plist[out].plist = NULL;
2105 }
2106 if (gfilter->aslist[out].name)
2107 {
2108 if (pfilter->aslist[out].name)
2109 free (pfilter->aslist[out].name);
2110 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
2111 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
2112 }
2113 else
2114 {
2115 if (pfilter->aslist[out].name)
2116 free (pfilter->aslist[out].name);
2117 pfilter->aslist[out].name = NULL;
2118 pfilter->aslist[out].aslist = NULL;
2119 }
fee0f4c6 2120 if (gfilter->map[RMAP_OUT].name)
2121 {
2122 if (pfilter->map[RMAP_OUT].name)
2123 free (pfilter->map[RMAP_OUT].name);
2124 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
2125 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
2126 }
2127 else
2128 {
2129 if (pfilter->map[RMAP_OUT].name)
2130 free (pfilter->map[RMAP_OUT].name);
2131 pfilter->map[RMAP_OUT].name = NULL;
2132 pfilter->map[RMAP_OUT].map = NULL;
2133 }
2134
2135 /* RS-client's import/export route-maps. */
2136 if (gfilter->map[RMAP_IMPORT].name)
718e3744 2137 {
fee0f4c6 2138 if (pfilter->map[RMAP_IMPORT].name)
2139 free (pfilter->map[RMAP_IMPORT].name);
2140 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
2141 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
718e3744 2142 }
2143 else
2144 {
fee0f4c6 2145 if (pfilter->map[RMAP_IMPORT].name)
2146 free (pfilter->map[RMAP_IMPORT].name);
2147 pfilter->map[RMAP_IMPORT].name = NULL;
2148 pfilter->map[RMAP_IMPORT].map = NULL;
2149 }
2150 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
2151 {
2152 if (pfilter->map[RMAP_EXPORT].name)
2153 free (pfilter->map[RMAP_EXPORT].name);
2154 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
2155 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
718e3744 2156 }
2157
2158 if (gfilter->usmap.name)
2159 {
2160 if (pfilter->usmap.name)
2161 free (pfilter->usmap.name);
2162 pfilter->usmap.name = strdup (gfilter->usmap.name);
2163 pfilter->usmap.map = gfilter->usmap.map;
2164 }
2165 else
2166 {
2167 if (pfilter->usmap.name)
2168 free (pfilter->usmap.name);
2169 pfilter->usmap.name = NULL;
2170 pfilter->usmap.map = NULL;
2171 }
c43ed2e4
DS
2172
2173 bgp_bfd_peer_group2peer_copy(conf, peer);
718e3744 2174}
2175
2176/* Peer group's remote AS configuration. */
2177int
0299c004
DS
2178peer_group_remote_as (struct bgp *bgp, const char *group_name,
2179 as_t *as, int as_type)
718e3744 2180{
2181 struct peer_group *group;
2182 struct peer *peer;
1eb8ef25 2183 struct listnode *node, *nnode;
718e3744 2184
2185 group = peer_group_lookup (bgp, group_name);
2186 if (! group)
2187 return -1;
2188
0299c004 2189 if ((as_type == group->conf->as_type) && (group->conf->as == *as))
718e3744 2190 return 0;
2191
0299c004 2192
718e3744 2193 /* When we setup peer-group AS number all peer group member's AS
2194 number must be updated to same number. */
0299c004 2195 peer_as_change (group->conf, *as, as_type);
718e3744 2196
1eb8ef25 2197 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2198 {
2199 if (peer->as != *as)
0299c004 2200 peer_as_change (peer, *as, as_type);
718e3744 2201 }
2202
2203 return 0;
2204}
2205
2206int
2207peer_group_delete (struct peer_group *group)
2208{
2209 struct bgp *bgp;
2210 struct peer *peer;
f14e6fdb 2211 struct prefix *prefix;
1ff9a340 2212 struct peer *other;
1eb8ef25 2213 struct listnode *node, *nnode;
f14e6fdb 2214 afi_t afi;
718e3744 2215
2216 bgp = group->bgp;
2217
1eb8ef25 2218 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2219 {
1ff9a340 2220 other = peer->doppelganger;
718e3744 2221 peer_delete (peer);
1ff9a340
DS
2222 if (other && other->status != Deleted)
2223 {
2224 other->group = NULL;
2225 peer_delete(other);
2226 }
718e3744 2227 }
2228 list_delete (group->peer);
2229
f14e6fdb
DS
2230 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2231 {
2232 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2233 {
2234 prefix_free(prefix);
2235 }
2236 list_delete (group->listen_range[afi]);
2237 }
2238
718e3744 2239 free (group->name);
2240 group->name = NULL;
2241
2242 group->conf->group = NULL;
2243 peer_delete (group->conf);
2244
2245 /* Delete from all peer_group list. */
2246 listnode_delete (bgp->group, group);
2247
7f342629 2248 bfd_info_free(&(group->conf->bfd_info));
c43ed2e4 2249
718e3744 2250 peer_group_free (group);
2251
2252 return 0;
2253}
2254
2255int
2256peer_group_remote_as_delete (struct peer_group *group)
2257{
1ff9a340 2258 struct peer *peer, *other;
1eb8ef25 2259 struct listnode *node, *nnode;
718e3744 2260
0299c004
DS
2261 if ((group->conf->as_type == AS_UNSPECIFIED) ||
2262 ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
718e3744 2263 return 0;
2264
1eb8ef25 2265 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2266 {
1ff9a340
DS
2267 other = peer->doppelganger;
2268
718e3744 2269 peer_delete (peer);
1ff9a340
DS
2270
2271 if (other && other->status != Deleted)
2272 {
2273 other->group = NULL;
2274 peer_delete(other);
2275 }
718e3744 2276 }
2277 list_delete_all_node (group->peer);
2278
2279 group->conf->as = 0;
0299c004 2280 group->conf->as_type = AS_UNSPECIFIED;
718e3744 2281
2282 return 0;
2283}
2284
f14e6fdb
DS
2285int
2286peer_group_listen_range_add (struct peer_group *group, struct prefix *range)
2287{
2288 struct prefix *prefix;
2289 struct listnode *node, *nnode;
2290 afi_t afi;
2291
2292 afi = family2afi(range->family);
2293
2294 /* Group needs remote AS configured. */
2295 if (! group->conf->as)
2296 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2297
2298 /* Ensure no duplicates. Currently we don't care about overlaps. */
2299 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2300 {
2301 if (prefix_same(range, prefix))
2302 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS;
2303 }
2304
2305 prefix = prefix_new();
2306 prefix_copy(prefix, range);
2307 listnode_add(group->listen_range[afi], prefix);
2308 return 0;
2309}
2310
2311int
2312peer_group_listen_range_del (struct peer_group *group, struct prefix *range)
2313{
2314 struct prefix *prefix, *prefix2;
2315 struct listnode *node, *nnode;
2316 struct peer *peer;
2317 afi_t afi;
2318 char buf[SU_ADDRSTRLEN];
2319
2320 afi = family2afi(range->family);
2321
2322 /* Identify the listen range. */
2323 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2324 {
2325 if (prefix_same(range, prefix))
2326 break;
2327 }
2328
2329 if (!prefix)
2330 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND;
2331
2332 prefix2str(prefix, buf, sizeof(buf));
2333
2334 /* Dispose off any dynamic neighbors that exist due to this listen range */
2335 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2336 {
2337 if (!peer_dynamic_neighbor (peer))
2338 continue;
2339
2340 prefix2 = sockunion2hostprefix(&peer->su);
2341 if (prefix_match(prefix, prefix2))
2342 {
2343 if (bgp_debug_neighbor_events(peer))
2344 zlog_debug ("Deleting dynamic neighbor %s group %s upon "
2345 "delete of listen range %s",
2346 peer->host, group->name, buf);
2347 peer_delete (peer);
2348 }
2349 }
2350
2351 /* Get rid of the listen range */
2352 listnode_delete(group->listen_range[afi], prefix);
2353
2354 return 0;
2355}
2356
718e3744 2357/* Bind specified peer to peer group. */
2358int
a80beece 2359peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
718e3744 2360 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
2361{
718e3744 2362 int first_member = 0;
2363
2364 /* Check peer group's address family. */
2365 if (! group->conf->afc[afi][safi])
2366 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
2367
2368 /* Lookup the peer. */
a80beece
DS
2369 if (!peer)
2370 peer = peer_lookup (bgp, su);
718e3744 2371
2372 /* Create a new peer. */
2373 if (! peer)
2374 {
0299c004 2375 if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as)) {
718e3744 2376 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
0299c004 2377 }
718e3744 2378
0299c004 2379 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, afi, safi);
718e3744 2380 peer->group = group;
2381 peer->af_group[afi][safi] = 1;
200df115 2382
ca058a30 2383 peer = peer_lock (peer); /* group->peer list reference */
718e3744 2384 listnode_add (group->peer, peer);
2385 peer_group2peer_config_copy (group, peer, afi, safi);
1ff9a340 2386 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2387
2388 return 0;
2389 }
2390
2391 /* When the peer already belongs to peer group, check the consistency. */
2392 if (peer->af_group[afi][safi])
2393 {
2394 if (strcmp (peer->group->name, group->name) != 0)
2395 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
2396
2397 return 0;
2398 }
2399
2400 /* Check current peer group configuration. */
2401 if (peer_group_active (peer)
2402 && strcmp (peer->group->name, group->name) != 0)
2403 return BGP_ERR_PEER_GROUP_MISMATCH;
2404
0299c004
DS
2405 if (peer->as_type == AS_UNSPECIFIED)
2406 {
2407 peer->as_type = group->conf->as_type;
2408 peer->as = group->conf->as;
2409 }
2410
718e3744 2411 if (! group->conf->as)
2412 {
2413 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
2414 && peer_sort (group->conf) != peer_sort (peer))
2415 {
2416 if (as)
2417 *as = peer->as;
2418 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
2419 }
2420
2421 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
2422 first_member = 1;
2423 }
2424
2425 peer->af_group[afi][safi] = 1;
2426 peer->afc[afi][safi] = 1;
3f9c7369
DS
2427 if (!peer_af_find(peer, afi, safi) &&
2428 peer_af_create(peer, afi, safi) == NULL)
2429 {
2430 zlog_err("couldn't create af structure for peer %s", peer->host);
2431 }
718e3744 2432 if (! peer->group)
2433 {
2434 peer->group = group;
200df115 2435
ca058a30 2436 peer = peer_lock (peer); /* group->peer list reference */
718e3744 2437 listnode_add (group->peer, peer);
2438 }
ca058a30
PJ
2439 else
2440 assert (group && peer->group == group);
718e3744 2441
2442 if (first_member)
2443 {
2444 /* Advertisement-interval reset */
966f821c 2445 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
ffd0c037
DS
2446 {
2447 if (peer_sort (group->conf) == BGP_PEER_IBGP)
2448 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
2449 else
2450 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
2451 }
718e3744 2452
2453 /* ebgp-multihop reset */
2454 if (peer_sort (group->conf) == BGP_PEER_IBGP)
2455 group->conf->ttl = 255;
2456
2457 /* local-as reset */
2458 if (peer_sort (group->conf) != BGP_PEER_EBGP)
2459 {
2460 group->conf->change_local_as = 0;
2461 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 2462 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 2463 }
2464 }
fee0f4c6 2465
2466 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2467 {
ca058a30
PJ
2468 struct listnode *pn;
2469
fee0f4c6 2470 /* If it's not configured as RSERVER_CLIENT in any other address
2471 family, without being member of a peer_group, remove it from
2472 list bgp->rsclient.*/
ca058a30
PJ
2473 if (! peer_rsclient_active (peer)
2474 && (pn = listnode_lookup (bgp->rsclient, peer)))
200df115 2475 {
2476 peer_unlock (peer); /* peer rsclient reference */
ca058a30 2477 list_delete_node (bgp->rsclient, pn);
228da428
CC
2478
2479 /* Clear our own rsclient rib for this afi/safi. */
2480 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
200df115 2481 }
fee0f4c6 2482
b608d5b5 2483 bgp_table_finish (&peer->rib[afi][safi]);
fee0f4c6 2484
2485 /* Import policy. */
2486 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
2487 {
2488 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
2489 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
2490 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
2491 }
2492
2493 /* Export policy. */
2494 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2495 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
2496 {
2497 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
2498 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
2499 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
2500 }
2501 }
2502
718e3744 2503 peer_group2peer_config_copy (group, peer, afi, safi);
1ff9a340 2504 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2505
6aa136f1 2506 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 2507 {
2508 peer->last_reset = PEER_DOWN_RMAP_BIND;
2509 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2510 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2511 }
718e3744 2512 else
1ff9a340 2513 bgp_session_reset(peer);
718e3744 2514
2515 return 0;
2516}
2517
2518int
2519peer_group_unbind (struct bgp *bgp, struct peer *peer,
2520 struct peer_group *group, afi_t afi, safi_t safi)
2521{
1ff9a340
DS
2522 struct peer *other;
2523
718e3744 2524 if (! peer->af_group[afi][safi])
2525 return 0;
2526
2527 if (group != peer->group)
2528 return BGP_ERR_PEER_GROUP_MISMATCH;
2529
2530 peer->af_group[afi][safi] = 0;
2531 peer->afc[afi][safi] = 0;
2532 peer_af_flag_reset (peer, afi, safi);
3f9c7369
DS
2533 if (peer_af_delete(peer, afi, safi) != 0)
2534 {
2535 zlog_err("couldn't delete af structure for peer %s", peer->host);
2536 }
718e3744 2537
fee0f4c6 2538 if (peer->rib[afi][safi])
2539 peer->rib[afi][safi] = NULL;
2540
718e3744 2541 if (! peer_group_active (peer))
2542 {
ca058a30 2543 assert (listnode_lookup (group->peer, peer));
200df115 2544 peer_unlock (peer); /* peer group list reference */
718e3744 2545 listnode_delete (group->peer, peer);
2546 peer->group = NULL;
1ff9a340 2547 other = peer->doppelganger;
718e3744 2548 if (group->conf->as)
2549 {
2550 peer_delete (peer);
1ff9a340
DS
2551 if (other && other->status != Deleted)
2552 {
2553 if (other->group)
2554 {
2555 peer_unlock(other);
2556 listnode_delete(group->peer, other);
2557 }
2558 other->group = NULL;
2559 peer_delete(other);
2560 }
718e3744 2561 return 0;
2562 }
7f342629 2563 bgp_bfd_deregister_peer(peer);
718e3744 2564 peer_global_config_reset (peer);
2565 }
2566
6aa136f1 2567 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 2568 {
2569 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2570 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2571 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2572 }
718e3744 2573 else
1ff9a340 2574 bgp_session_reset(peer);
718e3744 2575
2576 return 0;
2577}
6b0655a2 2578
fe7d2a48
DS
2579static int
2580bgp_startup_timer_expire (struct thread *thread)
2581{
2582 struct bgp *bgp;
2583
2584 bgp = THREAD_ARG (thread);
2585 bgp->t_startup = NULL;
2586
2587 return 0;
2588}
2589
2590
718e3744 2591/* BGP instance creation by `router bgp' commands. */
94f2b392 2592static struct bgp *
fd79ac91 2593bgp_create (as_t *as, const char *name)
718e3744 2594{
2595 struct bgp *bgp;
2596 afi_t afi;
2597 safi_t safi;
2598
200df115 2599 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2600 return NULL;
2601
0088b5dc 2602 bgp_lock (bgp);
6f58544d 2603 bgp->peer_self = peer_new (bgp);
228da428 2604 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
718e3744 2605
2606 bgp->peer = list_new ();
2607 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2608
2609 bgp->group = list_new ();
2610 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2611
fee0f4c6 2612 bgp->rsclient = list_new ();
2613 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2614
718e3744 2615 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2616 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2617 {
64e580a7
PJ
2618 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2619 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2620 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
165b5fff
JB
2621 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2622 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
718e3744 2623 }
2624
f188f2c4 2625 bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
718e3744 2626 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
3f9c7369 2627 bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
718e3744 2628 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2629 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
538621f2 2630 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2631 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
f14e6fdb
DS
2632 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
2633 bgp->dynamic_neighbors_count = 0;
718e3744 2634
2635 bgp->as = *as;
2636
2637 if (name)
2638 bgp->name = strdup (name);
2639
cb1faec9 2640 bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
3f9c7369 2641 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
cb1faec9 2642
fe7d2a48
DS
2643 THREAD_TIMER_ON (master, bgp->t_startup, bgp_startup_timer_expire,
2644 bgp, bgp->restart_time);
2645
3d68677e 2646 update_bgp_group_init(bgp);
718e3744 2647 return bgp;
2648}
2649
2650/* Return first entry of BGP. */
2651struct bgp *
94f2b392 2652bgp_get_default (void)
718e3744 2653{
2654 if (bm->bgp->head)
1eb8ef25 2655 return (listgetdata (listhead (bm->bgp)));
718e3744 2656 return NULL;
2657}
2658
2659/* Lookup BGP entry. */
2660struct bgp *
fd79ac91 2661bgp_lookup (as_t as, const char *name)
718e3744 2662{
2663 struct bgp *bgp;
1eb8ef25 2664 struct listnode *node, *nnode;
718e3744 2665
1eb8ef25 2666 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2667 if (bgp->as == as
2668 && ((bgp->name == NULL && name == NULL)
2669 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2670 return bgp;
2671 return NULL;
2672}
2673
2674/* Lookup BGP structure by view name. */
2675struct bgp *
fd79ac91 2676bgp_lookup_by_name (const char *name)
718e3744 2677{
2678 struct bgp *bgp;
1eb8ef25 2679 struct listnode *node, *nnode;
718e3744 2680
1eb8ef25 2681 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2682 if ((bgp->name == NULL && name == NULL)
2683 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2684 return bgp;
2685 return NULL;
2686}
2687
2688/* Called from VTY commands. */
2689int
fd79ac91 2690bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
718e3744 2691{
2692 struct bgp *bgp;
2693
2694 /* Multiple instance check. */
2695 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2696 {
2697 if (name)
2698 bgp = bgp_lookup_by_name (name);
2699 else
2700 bgp = bgp_get_default ();
2701
2702 /* Already exists. */
2703 if (bgp)
2704 {
2705 if (bgp->as != *as)
2706 {
2707 *as = bgp->as;
2708 return BGP_ERR_INSTANCE_MISMATCH;
2709 }
2710 *bgp_val = bgp;
2711 return 0;
2712 }
2713 }
2714 else
2715 {
2716 /* BGP instance name can not be specified for single instance. */
2717 if (name)
2718 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2719
2720 /* Get default BGP structure if exists. */
2721 bgp = bgp_get_default ();
2722
2723 if (bgp)
2724 {
2725 if (bgp->as != *as)
2726 {
2727 *as = bgp->as;
2728 return BGP_ERR_AS_MISMATCH;
2729 }
2730 *bgp_val = bgp;
2731 return 0;
2732 }
2733 }
2734
1758dbaa
SA
2735 bgp = bgp_create (as, name);
2736 bgp_router_id_set(bgp, &router_id_zebra);
2737 *bgp_val = bgp;
2738
0de4848d 2739 bgp->t_rmap_def_originate_eval = NULL;
518f0eb1
DS
2740 bgp->t_rmap_update = NULL;
2741 bgp->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
2742
ad12dde6 2743 /* Create BGP server socket, if first instance. */
cccbc015
PJ
2744 if (list_isempty(bm->bgp)
2745 && !bgp_option_check (BGP_OPT_NO_LISTEN))
ad12dde6
PJ
2746 {
2747 if (bgp_socket (bm->port, bm->address) < 0)
2748 return BGP_ERR_INVALID_VALUE;
2749 }
2750
718e3744 2751 listnode_add (bm->bgp, bgp);
718e3744 2752
2753 return 0;
2754}
2755
2756/* Delete BGP instance. */
2757int
2758bgp_delete (struct bgp *bgp)
2759{
2760 struct peer *peer;
b6b7cff2 2761 struct peer_group *group;
1eb8ef25 2762 struct listnode *node;
718e3744 2763 struct listnode *next;
2764 afi_t afi;
718e3744 2765 int i;
2766
d4a7a753
DS
2767 THREAD_OFF (bgp->t_startup);
2768
cd92e548
DS
2769 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2770 {
2771 if (peer->status == Established ||
2772 peer->status == OpenSent ||
2773 peer->status == OpenConfirm)
2774 {
2775 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2776 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2777 }
2778 }
2779
518f0eb1
DS
2780 if (bgp->t_rmap_update)
2781 BGP_TIMER_OFF(bgp->t_rmap_update);
2782
718e3744 2783 /* Delete static route. */
2784 bgp_static_delete (bgp);
2785
2786 /* Unset redistribution. */
2787 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2788 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2789 if (i != ZEBRA_ROUTE_BGP)
7c8ff89e 2790 bgp_redistribute_unset (bgp, afi, i, 0);
718e3744 2791
228da428 2792 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
6aa136f1
VS
2793 {
2794 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2795 {
2796 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2797 {
2798 /* Send notify to remote peer. */
2799 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2800 }
2801 }
2802 peer_group_delete (group);
2803 }
228da428 2804
1ff9a340
DS
2805 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2806 {
2807 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2808 {
2809 /* Send notify to remote peer. */
2810 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2811 }
2812
2813 peer_delete (peer);
2814 }
2815
228da428 2816 assert (listcount (bgp->rsclient) == 0);
0088b5dc
SH
2817
2818 if (bgp->peer_self) {
2819 peer_delete(bgp->peer_self);
2820 bgp->peer_self = NULL;
2821 }
0de4848d
DS
2822
2823 if (bgp->t_rmap_def_originate_eval)
2824 {
2825 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
2826 bgp_unlock(bgp);
2827 }
3d68677e
DS
2828
2829 update_bgp_group_free (bgp);
fd35b948
PJ
2830 /* Remove visibility via the master list - there may however still be
2831 * routes to be processed still referencing the struct bgp.
2832 */
2833 listnode_delete (bm->bgp, bgp);
d023aec4
SH
2834 if (list_isempty(bm->bgp))
2835 bgp_close ();
2836
0088b5dc 2837 bgp_unlock(bgp); /* initial reference */
6410e93a 2838
0088b5dc
SH
2839 return 0;
2840}
2841
2842static void bgp_free (struct bgp *);
2843
2844void
2845bgp_lock (struct bgp *bgp)
2846{
2847 ++bgp->lock;
2848}
2849
2850void
2851bgp_unlock(struct bgp *bgp)
2852{
228da428 2853 assert(bgp->lock > 0);
0088b5dc
SH
2854 if (--bgp->lock == 0)
2855 bgp_free (bgp);
2856}
2857
2858static void
2859bgp_free (struct bgp *bgp)
2860{
2861 afi_t afi;
2862 safi_t safi;
2863
2864 list_delete (bgp->group);
2865 list_delete (bgp->peer);
fee0f4c6 2866 list_delete (bgp->rsclient);
2867
718e3744 2868 if (bgp->name)
2869 free (bgp->name);
2870
2871 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2872 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2873 {
2874 if (bgp->route[afi][safi])
228da428 2875 bgp_table_finish (&bgp->route[afi][safi]);
718e3744 2876 if (bgp->aggregate[afi][safi])
228da428 2877 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
718e3744 2878 if (bgp->rib[afi][safi])
228da428 2879 bgp_table_finish (&bgp->rib[afi][safi]);
718e3744 2880 }
2881 XFREE (MTYPE_BGP, bgp);
718e3744 2882}
6b0655a2 2883
a80beece
DS
2884struct peer *
2885peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if)
2886{
2887 struct peer *peer;
2888 struct listnode *node, *nnode;
2889
2890 if (!conf_if)
2891 return NULL;
2892
2893 if (bgp != NULL)
2894 {
2895 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2896 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
2897 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2898 return peer;
2899 }
2900 else if (bm->bgp != NULL)
2901 {
2902 struct listnode *bgpnode, *nbgpnode;
2903
2904 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2905 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2906 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
2907 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2908 return peer;
2909 }
2910 return NULL;
2911}
2912
718e3744 2913struct peer *
2914peer_lookup (struct bgp *bgp, union sockunion *su)
2915{
2916 struct peer *peer;
1eb8ef25 2917 struct listnode *node, *nnode;
718e3744 2918
fc4dc59d 2919 if (bgp != NULL)
fc4dc59d 2920 {
2158ad23
PJ
2921 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2922 if (sockunion_same (&peer->su, su)
1ff9a340 2923 && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
2158ad23 2924 return peer;
fc4dc59d 2925 }
fc4dc59d 2926 else if (bm->bgp != NULL)
718e3744 2927 {
2158ad23
PJ
2928 struct listnode *bgpnode, *nbgpnode;
2929
2930 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2931 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2932 if (sockunion_same (&peer->su, su)
1ff9a340 2933 && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
2158ad23 2934 return peer;
fc4dc59d 2935 }
718e3744 2936 return NULL;
2937}
2938
f14e6fdb
DS
2939struct peer *
2940peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
2941 struct peer_group *group)
2942{
2943 struct peer *peer;
2944 afi_t afi;
2945 safi_t safi;
f14e6fdb
DS
2946
2947 /* Create peer first; we've already checked group config is valid. */
0299c004 2948 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0);
f14e6fdb
DS
2949 if (!peer)
2950 return NULL;
2951
2952 /* Link to group */
2953 peer->group = group;
2954 peer = peer_lock (peer);
2955 listnode_add (group->peer, peer);
2956
2957 /*
2958 * Bind peer for all AFs configured for the group. We don't call
2959 * peer_group_bind as that is sub-optimal and does some stuff we don't want.
2960 */
2961 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2962 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2963 {
2964 if (!group->conf->afc[afi][safi])
2965 continue;
2966 peer->af_group[afi][safi] = 1;
2967 peer->afc[afi][safi] = 1;
2968 if (!peer_af_find(peer, afi, safi) &&
2969 peer_af_create(peer, afi, safi) == NULL)
2970 {
2971 zlog_err("couldn't create af structure for peer %s", peer->host);
2972 }
2973 peer_group2peer_config_copy (group, peer, afi, safi);
2974 }
2975
2976 /* Mark as dynamic, but also as a "config node" for other things to work. */
2977 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
2978 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
2979
2980 return peer;
2981}
2982
2983struct prefix *
2984peer_group_lookup_dynamic_neighbor_range (struct peer_group * group,
2985 struct prefix * prefix)
2986{
2987 struct listnode *node, *nnode;
2988 struct prefix *range;
2989 afi_t afi;
2990
2991 afi = family2afi(prefix->family);
2992
2993 if (group->listen_range[afi])
2994 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range))
2995 if (prefix_match(range, prefix))
2996 return range;
2997
2998 return NULL;
2999}
3000
3001struct peer_group *
3002peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix,
3003 struct prefix **listen_range)
3004{
3005 struct prefix *range = NULL;
3006 struct peer_group *group = NULL;
3007 struct listnode *node, *nnode;
3008
3009 *listen_range = NULL;
3010 if (bgp != NULL)
3011 {
3012 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3013 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
3014 break;
3015 }
3016 else if (bm->bgp != NULL)
3017 {
3018 struct listnode *bgpnode, *nbgpnode;
3019
3020 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3021 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3022 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
3023 break;
3024 }
3025
3026 *listen_range = range;
3027 return (group && range) ? group : NULL;
3028}
3029
3030struct peer *
3031peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
3032{
3033 struct peer_group *group;
3034 struct bgp *gbgp;
3035 struct peer *peer;
3036 struct prefix *prefix;
3037 struct prefix *listen_range;
3038 int dncount;
3039 char buf[SU_ADDRSTRLEN];
3040 char buf1[SU_ADDRSTRLEN];
3041
3042 prefix = sockunion2hostprefix(su);
0299c004 3043 if (!prefix) {
f14e6fdb 3044 return NULL;
0299c004 3045 }
f14e6fdb
DS
3046
3047 /* See if incoming connection matches a configured listen range. */
3048 group = peer_group_lookup_dynamic_neighbor (bgp, prefix, &listen_range);
3049
3050 if (! group)
3051 return NULL;
3052
0299c004 3053
f14e6fdb
DS
3054 gbgp = group->bgp;
3055
3056 if (! gbgp)
3057 return NULL;
3058
3059 prefix2str(prefix, buf, sizeof(buf));
3060 prefix2str(listen_range, buf1, sizeof(buf1));
3061
3062 if (bgp_debug_neighbor_events(NULL))
3063 zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s",
3064 buf, group->name, buf1);
3065
3066 /* Are we within the listen limit? */
3067 dncount = gbgp->dynamic_neighbors_count;
3068
3069 if (dncount >= gbgp->dynamic_neighbors_limit)
3070 {
3071 if (bgp_debug_neighbor_events(NULL))
3072 zlog_debug ("Dynamic Neighbor %s rejected - at limit %d",
3073 inet_sutop (su, buf), gbgp->dynamic_neighbors_limit);
3074 return NULL;
3075 }
3076
3077 /* Ensure group is not disabled. */
3078 if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN))
3079 {
3080 if (bgp_debug_neighbor_events(NULL))
3081 zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled",
3082 buf, group->name);
3083 return NULL;
3084 }
3085
3086 /* Check that at least one AF is activated for the group. */
3087 if (!peer_group_af_configured (group))
3088 {
3089 if (bgp_debug_neighbor_events(NULL))
3090 zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s",
3091 buf, group->name);
3092 return NULL;
3093 }
3094
3095 /* Create dynamic peer and bind to associated group. */
3096 peer = peer_create_bind_dynamic_neighbor (gbgp, su, group);
3097 assert (peer);
3098
3099 gbgp->dynamic_neighbors_count = ++dncount;
3100
3101 if (bgp_debug_neighbor_events(peer))
3102 zlog_debug ("%s Dynamic Neighbor added, group %s count %d",
3103 peer->host, group->name, dncount);
3104
3105 return peer;
3106}
3107
3108void peer_drop_dynamic_neighbor (struct peer *peer)
3109{
3110 int dncount = -1;
3111 if (peer->group && peer->group->bgp)
3112 {
3113 dncount = peer->group->bgp->dynamic_neighbors_count;
3114 if (dncount)
3115 peer->group->bgp->dynamic_neighbors_count = --dncount;
3116 }
3117 if (bgp_debug_neighbor_events(peer))
3118 zlog_debug ("%s dropped from group %s, count %d",
3119 peer->host, peer->group->name, dncount);
3120}
3121
3122
718e3744 3123/* If peer is configured at least one address family return 1. */
3124int
3125peer_active (struct peer *peer)
3126{
a80beece
DS
3127 if (BGP_PEER_SU_UNSPEC(peer))
3128 return 0;
718e3744 3129 if (peer->afc[AFI_IP][SAFI_UNICAST]
3130 || peer->afc[AFI_IP][SAFI_MULTICAST]
3131 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
3132 || peer->afc[AFI_IP6][SAFI_UNICAST]
3133 || peer->afc[AFI_IP6][SAFI_MULTICAST])
3134 return 1;
3135 return 0;
3136}
3137
3138/* If peer is negotiated at least one address family return 1. */
3139int
3140peer_active_nego (struct peer *peer)
3141{
3142 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3143 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3144 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
3145 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
3146 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
3147 return 1;
3148 return 0;
3149}
6b0655a2 3150
718e3744 3151/* peer_flag_change_type. */
3152enum peer_change_type
3153{
3154 peer_change_none,
3155 peer_change_reset,
3156 peer_change_reset_in,
3157 peer_change_reset_out,
3158};
3159
94f2b392 3160static void
718e3744 3161peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
3162 enum peer_change_type type)
3163{
3164 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3165 return;
3166
d9d4ae51
SH
3167 if (peer->status != Established)
3168 return;
3169
718e3744 3170 if (type == peer_change_reset)
1ff9a340
DS
3171 {
3172 /* If we're resetting session, we've to delete both peer struct */
3173 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3174 && (!CHECK_FLAG(peer->doppelganger->flags,
3175 PEER_FLAG_CONFIG_NODE)))
3176 peer_delete(peer->doppelganger);
3177
3178 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3179 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3180 }
718e3744 3181 else if (type == peer_change_reset_in)
3182 {
3183 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3184 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3185 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3186 else
1ff9a340
DS
3187 {
3188 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3189 && (!CHECK_FLAG(peer->doppelganger->flags,
3190 PEER_FLAG_CONFIG_NODE)))
3191 peer_delete(peer->doppelganger);
3192
3193 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3194 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3195 }
718e3744 3196 }
3197 else if (type == peer_change_reset_out)
3f9c7369
DS
3198 {
3199 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3200 bgp_announce_route (peer, afi, safi);
3201 }
718e3744 3202}
3203
3204struct peer_flag_action
3205{
3206 /* Peer's flag. */
3207 u_int32_t flag;
3208
3209 /* This flag can be set for peer-group member. */
3210 u_char not_for_member;
3211
3212 /* Action when the flag is changed. */
3213 enum peer_change_type type;
e0701b79 3214
3215 /* Peer down cause */
3216 u_char peer_down;
718e3744 3217};
3218
03621955 3219static const struct peer_flag_action peer_flag_action_list[] =
718e3744 3220 {
3221 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
3222 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
3223 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
3224 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
3225 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
718e3744 3226 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
6ffd2079 3227 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
8a92a8a0 3228 { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset },
718e3744 3229 { 0, 0, 0 }
3230 };
3231
03621955 3232static const struct peer_flag_action peer_af_flag_action_list[] =
718e3744 3233 {
3234 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
3235 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
3236 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
3237 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
3238 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
3239 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
3240 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
3241 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
3242 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
3243 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
5000f21c
DS
3244 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
3245 { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
718e3744 3246 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
3247 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
3248 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
fee0f4c6 3249 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
a538debe 3250 { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out },
c7122e14 3251 { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
718e3744 3252 { 0, 0, 0 }
3253 };
3254
3255/* Proper action set. */
94f2b392 3256static int
03621955 3257peer_flag_action_set (const struct peer_flag_action *action_list, int size,
718e3744 3258 struct peer_flag_action *action, u_int32_t flag)
3259{
3260 int i;
3261 int found = 0;
3262 int reset_in = 0;
3263 int reset_out = 0;
03621955 3264 const struct peer_flag_action *match = NULL;
718e3744 3265
3266 /* Check peer's frag action. */
3267 for (i = 0; i < size; i++)
3268 {
3269 match = &action_list[i];
3270
3271 if (match->flag == 0)
3272 break;
3273
3274 if (match->flag & flag)
3275 {
3276 found = 1;
3277
3278 if (match->type == peer_change_reset_in)
3279 reset_in = 1;
3280 if (match->type == peer_change_reset_out)
3281 reset_out = 1;
3282 if (match->type == peer_change_reset)
3283 {
3284 reset_in = 1;
3285 reset_out = 1;
3286 }
3287 if (match->not_for_member)
3288 action->not_for_member = 1;
3289 }
3290 }
3291
3292 /* Set peer clear type. */
3293 if (reset_in && reset_out)
3294 action->type = peer_change_reset;
3295 else if (reset_in)
3296 action->type = peer_change_reset_in;
3297 else if (reset_out)
3298 action->type = peer_change_reset_out;
3299 else
3300 action->type = peer_change_none;
3301
3302 return found;
3303}
3304
94f2b392 3305static void
718e3744 3306peer_flag_modify_action (struct peer *peer, u_int32_t flag)
3307{
3308 if (flag == PEER_FLAG_SHUTDOWN)
3309 {
3310 if (CHECK_FLAG (peer->flags, flag))
3311 {
93406d87 3312 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3313 peer_nsf_stop (peer);
3314
0a486e5f 3315 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3316 if (peer->t_pmax_restart)
3317 {
3318 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 3319 if (bgp_debug_neighbor_events(peer))
0a486e5f 3320 zlog_debug ("%s Maximum-prefix restart timer canceled",
3321 peer->host);
3322 }
3323
1ff9a340
DS
3324 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3325 peer_nsf_stop (peer);
93406d87 3326
6aa136f1 3327 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3328 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3329 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3330 else
1ff9a340 3331 bgp_session_reset(peer);
718e3744 3332 }
3333 else
3334 {
3335 peer->v_start = BGP_INIT_START_TIMER;
3336 BGP_EVENT_ADD (peer, BGP_Stop);
3337 }
3338 }
6aa136f1 3339 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3340 {
c9502438 3341 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3342 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3343 else if (flag == PEER_FLAG_PASSIVE)
3344 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
6ffd2079 3345 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
c9502438 3346 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
e0701b79 3347
c9502438 3348 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3349 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
718e3744 3350 }
3351 else
1ff9a340 3352 bgp_session_reset(peer);
718e3744 3353}
3354
3355/* Change specified peer flag. */
94f2b392 3356static int
718e3744 3357peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
3358{
3359 int found;
3360 int size;
3361 struct peer_group *group;
1eb8ef25 3362 struct listnode *node, *nnode;
718e3744 3363 struct peer_flag_action action;
3364
3365 memset (&action, 0, sizeof (struct peer_flag_action));
3366 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
3367
3368 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
3369
3370 /* No flag action is found. */
3371 if (! found)
3372 return BGP_ERR_INVALID_FLAG;
3373
3374 /* Not for peer-group member. */
3375 if (action.not_for_member && peer_group_active (peer))
3376 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3377
3378 /* When unset the peer-group member's flag we have to check
3379 peer-group configuration. */
3380 if (! set && peer_group_active (peer))
3381 if (CHECK_FLAG (peer->group->conf->flags, flag))
3382 {
3383 if (flag == PEER_FLAG_SHUTDOWN)
3384 return BGP_ERR_PEER_GROUP_SHUTDOWN;
3385 else
3386 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3387 }
3388
3389 /* Flag conflict check. */
3390 if (set
3391 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
3392 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
3393 return BGP_ERR_PEER_FLAG_CONFLICT;
3394
3395 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3396 {
3397 if (set && CHECK_FLAG (peer->flags, flag) == flag)
3398 return 0;
3399 if (! set && ! CHECK_FLAG (peer->flags, flag))
3400 return 0;
3401 }
3402
3403 if (set)
3404 SET_FLAG (peer->flags, flag);
3405 else
3406 UNSET_FLAG (peer->flags, flag);
3407
3408 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3409 {
3410 if (action.type == peer_change_reset)
3411 peer_flag_modify_action (peer, flag);
3412
3413 return 0;
3414 }
3415
3416 /* peer-group member updates. */
3417 group = peer->group;
3418
1eb8ef25 3419 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3420 {
3421 if (set && CHECK_FLAG (peer->flags, flag) == flag)
3422 continue;
3423
3424 if (! set && ! CHECK_FLAG (peer->flags, flag))
3425 continue;
3426
3427 if (set)
3428 SET_FLAG (peer->flags, flag);
3429 else
3430 UNSET_FLAG (peer->flags, flag);
3431
3432 if (action.type == peer_change_reset)
3433 peer_flag_modify_action (peer, flag);
3434 }
3435 return 0;
3436}
3437
3438int
3439peer_flag_set (struct peer *peer, u_int32_t flag)
3440{
3441 return peer_flag_modify (peer, flag, 1);
3442}
3443
3444int
3445peer_flag_unset (struct peer *peer, u_int32_t flag)
3446{
3447 return peer_flag_modify (peer, flag, 0);
3448}
3449
94f2b392 3450static int
718e3744 3451peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
3452{
3453 if (peer->af_group[afi][safi])
3454 return 1;
3455 return 0;
3456}
3457
94f2b392 3458static int
718e3744 3459peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
3460 int set)
3461{
3462 int found;
3463 int size;
1eb8ef25 3464 struct listnode *node, *nnode;
718e3744 3465 struct peer_group *group;
3466 struct peer_flag_action action;
3467
3468 memset (&action, 0, sizeof (struct peer_flag_action));
3469 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
3470
3471 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
3472
3473 /* No flag action is found. */
3474 if (! found)
3475 return BGP_ERR_INVALID_FLAG;
3476
3477 /* Adress family must be activated. */
3478 if (! peer->afc[afi][safi])
3479 return BGP_ERR_PEER_INACTIVE;
3480
3481 /* Not for peer-group member. */
3482 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
3483 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3484
3485 /* Spcecial check for reflector client. */
3486 if (flag & PEER_FLAG_REFLECTOR_CLIENT
3487 && peer_sort (peer) != BGP_PEER_IBGP)
3488 return BGP_ERR_NOT_INTERNAL_PEER;
3489
3490 /* Spcecial check for remove-private-AS. */
3491 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
3492 && peer_sort (peer) == BGP_PEER_IBGP)
3493 return BGP_ERR_REMOVE_PRIVATE_AS;
3494
c7122e14
DS
3495 /* as-override is not allowed for IBGP peers */
3496 if (flag & PEER_FLAG_AS_OVERRIDE
3497 && peer_sort (peer) == BGP_PEER_IBGP)
3498 return BGP_ERR_AS_OVERRIDE;
3499
718e3744 3500 /* When unset the peer-group member's flag we have to check
3501 peer-group configuration. */
3502 if (! set && peer->af_group[afi][safi])
3503 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
3504 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3505
3506 /* When current flag configuration is same as requested one. */
3507 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3508 {
3509 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
3510 return 0;
3511 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
3512 return 0;
3513 }
3514
3515 if (set)
3516 SET_FLAG (peer->af_flags[afi][safi], flag);
3517 else
3518 UNSET_FLAG (peer->af_flags[afi][safi], flag);
3519
3520 /* Execute action when peer is established. */
3521 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3522 && peer->status == Established)
3523 {
3524 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
3525 bgp_clear_adj_in (peer, afi, safi);
3526 else
e0701b79 3527 {
3528 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3529 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3530 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3531 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3532 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3533 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3534 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3535 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3536
3537 peer_change_action (peer, afi, safi, action.type);
3538 }
3539
718e3744 3540 }
3541
3542 /* Peer group member updates. */
3543 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3544 {
3545 group = peer->group;
3546
1eb8ef25 3547 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3548 {
3549 if (! peer->af_group[afi][safi])
3550 continue;
3551
3552 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
3553 continue;
3554
3555 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
3556 continue;
3557
3558 if (set)
3559 SET_FLAG (peer->af_flags[afi][safi], flag);
3560 else
3561 UNSET_FLAG (peer->af_flags[afi][safi], flag);
3562
3563 if (peer->status == Established)
3564 {
3565 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
3566 bgp_clear_adj_in (peer, afi, safi);
3567 else
e0701b79 3568 {
3569 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3570 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3571 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3572 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3573 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3574 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3575 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3576 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3577
3578 peer_change_action (peer, afi, safi, action.type);
3579 }
718e3744 3580 }
3581 }
3582 }
3583 return 0;
3584}
3585
3586int
3587peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3588{
3589 return peer_af_flag_modify (peer, afi, safi, flag, 1);
3590}
3591
3592int
3593peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3594{
3595 return peer_af_flag_modify (peer, afi, safi, flag, 0);
3596}
6b0655a2 3597
718e3744 3598/* EBGP multihop configuration. */
3599int
3600peer_ebgp_multihop_set (struct peer *peer, int ttl)
3601{
3602 struct peer_group *group;
1eb8ef25 3603 struct listnode *node, *nnode;
fa411a21 3604 struct peer *peer1;
718e3744 3605
a80beece 3606 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
718e3744 3607 return 0;
3608
fa411a21
NH
3609 /* see comment in peer_ttl_security_hops_set() */
3610 if (ttl != MAXTTL)
3611 {
3612 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3613 {
3614 group = peer->group;
3615 if (group->conf->gtsm_hops != 0)
3616 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3617
3618 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
3619 {
6d85b15b 3620 if (peer1->sort == BGP_PEER_IBGP)
fa411a21
NH
3621 continue;
3622
3623 if (peer1->gtsm_hops != 0)
3624 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3625 }
3626 }
3627 else
3628 {
3629 if (peer->gtsm_hops != 0)
3630 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3631 }
3632 }
3633
718e3744 3634 peer->ttl = ttl;
3635
3636 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3637 {
6d85b15b 3638 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
e5cc509c
DS
3639 {
3640 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3641 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3642 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3643 else
3644 bgp_session_reset(peer);
3645 }
718e3744 3646 }
3647 else
3648 {
3649 group = peer->group;
1eb8ef25 3650 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 3651 {
6d85b15b 3652 if (peer->sort == BGP_PEER_IBGP)
eb821189 3653 continue;
718e3744 3654
eb821189 3655 peer->ttl = group->conf->ttl;
718e3744 3656
e5cc509c
DS
3657 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3658 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3659 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3660 else
3661 bgp_session_reset(peer);
eb821189 3662 }
718e3744 3663 }
3664 return 0;
3665}
3666
3667int
3668peer_ebgp_multihop_unset (struct peer *peer)
3669{
3670 struct peer_group *group;
1eb8ef25 3671 struct listnode *node, *nnode;
718e3744 3672
6d85b15b 3673 if (peer->sort == BGP_PEER_IBGP)
718e3744 3674 return 0;
3675
fa411a21
NH
3676 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
3677 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3678
718e3744 3679 if (peer_group_active (peer))
3680 peer->ttl = peer->group->conf->ttl;
3681 else
3682 peer->ttl = 1;
3683
3684 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3685 {
e5cc509c
DS
3686 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3687 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3688 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3689 else
3690 bgp_session_reset(peer);
718e3744 3691 }
3692 else
3693 {
3694 group = peer->group;
1eb8ef25 3695 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 3696 {
6d85b15b 3697 if (peer->sort == BGP_PEER_IBGP)
eb821189 3698 continue;
3699
3700 peer->ttl = 1;
e5cc509c 3701
eb821189 3702 if (peer->fd >= 0)
e5cc509c
DS
3703 {
3704 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3705 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3706 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3707 else
3708 bgp_session_reset(peer);
3709 }
eb821189 3710 }
718e3744 3711 }
3712 return 0;
3713}
6b0655a2 3714
718e3744 3715/* Neighbor description. */
3716int
3717peer_description_set (struct peer *peer, char *desc)
3718{
3719 if (peer->desc)
3720 XFREE (MTYPE_PEER_DESC, peer->desc);
3721
3722 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
3723
3724 return 0;
3725}
3726
3727int
3728peer_description_unset (struct peer *peer)
3729{
3730 if (peer->desc)
3731 XFREE (MTYPE_PEER_DESC, peer->desc);
3732
3733 peer->desc = NULL;
3734
3735 return 0;
3736}
6b0655a2 3737
718e3744 3738/* Neighbor update-source. */
3739int
fd79ac91 3740peer_update_source_if_set (struct peer *peer, const char *ifname)
718e3744 3741{
3742 struct peer_group *group;
1eb8ef25 3743 struct listnode *node, *nnode;
718e3744 3744
3745 if (peer->update_if)
3746 {
3747 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3748 && strcmp (peer->update_if, ifname) == 0)
3749 return 0;
3750
3751 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3752 peer->update_if = NULL;
3753 }
3754
3755 if (peer->update_source)
3756 {
3757 sockunion_free (peer->update_source);
3758 peer->update_source = NULL;
3759 }
3760
3761 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3762
3763 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3764 {
6aa136f1 3765 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3766 {
3767 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3768 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3769 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3770 }
718e3744 3771 else
1ff9a340 3772 bgp_session_reset(peer);
718e3744 3773 return 0;
3774 }
3775
3776 /* peer-group member updates. */
3777 group = peer->group;
1eb8ef25 3778 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3779 {
3780 if (peer->update_if)
3781 {
3782 if (strcmp (peer->update_if, ifname) == 0)
3783 continue;
3784
3785 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3786 peer->update_if = NULL;
3787 }
3788
3789 if (peer->update_source)
3790 {
3791 sockunion_free (peer->update_source);
3792 peer->update_source = NULL;
3793 }
3794
3795 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3796
6aa136f1 3797 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3798 {
3799 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3800 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3801 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3802 }
718e3744 3803 else
1ff9a340 3804 bgp_session_reset(peer);
718e3744 3805 }
3806 return 0;
3807}
3808
3809int
3810peer_update_source_addr_set (struct peer *peer, union sockunion *su)
3811{
3812 struct peer_group *group;
1eb8ef25 3813 struct listnode *node, *nnode;
718e3744 3814
3815 if (peer->update_source)
3816 {
3817 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3818 && sockunion_cmp (peer->update_source, su) == 0)
3819 return 0;
3820 sockunion_free (peer->update_source);
3821 peer->update_source = NULL;
3822 }
3823
3824 if (peer->update_if)
3825 {
3826 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3827 peer->update_if = NULL;
1ff9a340 3828
718e3744 3829 }
3830
3831 peer->update_source = sockunion_dup (su);
3832
3833 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3834 {
6aa136f1 3835 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3836 {
3837 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3838 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3839 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3840 }
718e3744 3841 else
1ff9a340 3842 bgp_session_reset(peer);
718e3744 3843 return 0;
3844 }
3845
3846 /* peer-group member updates. */
3847 group = peer->group;
1eb8ef25 3848 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3849 {
3850 if (peer->update_source)
3851 {
3852 if (sockunion_cmp (peer->update_source, su) == 0)
3853 continue;
3854 sockunion_free (peer->update_source);
3855 peer->update_source = NULL;
3856 }
3857
3858 if (peer->update_if)
3859 {
3860 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3861 peer->update_if = NULL;
3862 }
3863
3864 peer->update_source = sockunion_dup (su);
3865
6aa136f1 3866 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3867 {
3868 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3869 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3870 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3871 }
718e3744 3872 else
1ff9a340 3873 bgp_session_reset(peer);
718e3744 3874 }
3875 return 0;
3876}
3877
3878int
3879peer_update_source_unset (struct peer *peer)
3880{
3881 union sockunion *su;
3882 struct peer_group *group;
1eb8ef25 3883 struct listnode *node, *nnode;
718e3744 3884
3885 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3886 && ! peer->update_source
3887 && ! peer->update_if)
3888 return 0;
3889
3890 if (peer->update_source)
3891 {
3892 sockunion_free (peer->update_source);
3893 peer->update_source = NULL;
3894 }
3895 if (peer->update_if)
3896 {
3897 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3898 peer->update_if = NULL;
3899 }
3900
3901 if (peer_group_active (peer))
3902 {
3903 group = peer->group;
3904
3905 if (group->conf->update_source)
3906 {
3907 su = sockunion_dup (group->conf->update_source);
3908 peer->update_source = su;
3909 }
3910 else if (group->conf->update_if)
3911 peer->update_if =
3912 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3913 }
3914
3915 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3916 {
6aa136f1 3917 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3918 {
3919 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3920 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3921 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3922 }
718e3744 3923 else
1ff9a340 3924 bgp_session_reset(peer);
718e3744 3925 return 0;
3926 }
3927
3928 /* peer-group member updates. */
3929 group = peer->group;
1eb8ef25 3930 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3931 {
3932 if (! peer->update_source && ! peer->update_if)
3933 continue;
3934
3935 if (peer->update_source)
3936 {
3937 sockunion_free (peer->update_source);
3938 peer->update_source = NULL;
3939 }
3940
3941 if (peer->update_if)
3942 {
3943 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3944 peer->update_if = NULL;
3945 }
3946
6aa136f1 3947 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3948 {
3949 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3950 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3951 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3952 }
718e3744 3953 else
1ff9a340 3954 bgp_session_reset(peer);
718e3744 3955 }
3956 return 0;
3957}
6b0655a2 3958
718e3744 3959int
3960peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
fd79ac91 3961 const char *rmap)
718e3744 3962{
3963 struct peer_group *group;
1eb8ef25 3964 struct listnode *node, *nnode;
718e3744 3965
3966 /* Adress family must be activated. */
3967 if (! peer->afc[afi][safi])
3968 return BGP_ERR_PEER_INACTIVE;
3969
3970 /* Default originate can't be used for peer group memeber. */
3971 if (peer_is_group_member (peer, afi, safi))
3972 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3973
3974 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3975 || (rmap && ! peer->default_rmap[afi][safi].name)
3976 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3977 {
3978 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3979
3980 if (rmap)
3981 {
3982 if (peer->default_rmap[afi][safi].name)
3983 free (peer->default_rmap[afi][safi].name);
3984 peer->default_rmap[afi][safi].name = strdup (rmap);
3985 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3986 }
3987 }
3988
3989 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3990 {
3f9c7369
DS
3991 if (peer->status == Established && peer->afc_nego[afi][safi]) {
3992 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 3993 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
3994 bgp_announce_route (peer, afi, safi);
3995 }
718e3744 3996 return 0;
3997 }
3998
3999 /* peer-group member updates. */
4000 group = peer->group;
1eb8ef25 4001 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4002 {
4003 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4004
4005 if (rmap)
4006 {
4007 if (peer->default_rmap[afi][safi].name)
4008 free (peer->default_rmap[afi][safi].name);
4009 peer->default_rmap[afi][safi].name = strdup (rmap);
4010 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
4011 }
4012
3f9c7369
DS
4013 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4014 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4015 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
4016 bgp_announce_route (peer, afi, safi);
4017 }
718e3744 4018 }
4019 return 0;
4020}
4021
4022int
4023peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
4024{
4025 struct peer_group *group;
1eb8ef25 4026 struct listnode *node, *nnode;
718e3744 4027
4028 /* Adress family must be activated. */
4029 if (! peer->afc[afi][safi])
4030 return BGP_ERR_PEER_INACTIVE;
4031
4032 /* Default originate can't be used for peer group memeber. */
4033 if (peer_is_group_member (peer, afi, safi))
4034 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4035
4036 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
4037 {
4038 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4039
4040 if (peer->default_rmap[afi][safi].name)
4041 free (peer->default_rmap[afi][safi].name);
4042 peer->default_rmap[afi][safi].name = NULL;
4043 peer->default_rmap[afi][safi].map = NULL;
4044 }
4045
4046 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4047 {
3f9c7369
DS
4048 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4049 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4050 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
4051 bgp_announce_route (peer, afi, safi);
4052 }
718e3744 4053 return 0;
4054 }
4055
4056 /* peer-group member updates. */
4057 group = peer->group;
1eb8ef25 4058 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4059 {
4060 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4061
4062 if (peer->default_rmap[afi][safi].name)
4063 free (peer->default_rmap[afi][safi].name);
4064 peer->default_rmap[afi][safi].name = NULL;
4065 peer->default_rmap[afi][safi].map = NULL;
4066
3f9c7369
DS
4067 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4068 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4069 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
4070 bgp_announce_route (peer, afi, safi);
4071 }
718e3744 4072 }
4073 return 0;
4074}
6b0655a2 4075
718e3744 4076int
4077peer_port_set (struct peer *peer, u_int16_t port)
4078{
4079 peer->port = port;
4080 return 0;
4081}
4082
4083int
4084peer_port_unset (struct peer *peer)
4085{
4086 peer->port = BGP_PORT_DEFAULT;
4087 return 0;
4088}
6b0655a2 4089
718e3744 4090/* neighbor weight. */
ffd0c037 4091void
718e3744 4092peer_weight_set (struct peer *peer, u_int16_t weight)
4093{
4094 struct peer_group *group;
1eb8ef25 4095 struct listnode *node, *nnode;
718e3744 4096
4097 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
4098 peer->weight = weight;
4099
4100 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
ffd0c037 4101 return;
718e3744 4102
4103 /* peer-group member updates. */
4104 group = peer->group;
1eb8ef25 4105 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4106 {
4107 peer->weight = group->conf->weight;
4108 }
718e3744 4109}
4110
ffd0c037 4111void
718e3744 4112peer_weight_unset (struct peer *peer)
4113{
4114 struct peer_group *group;
1eb8ef25 4115 struct listnode *node, *nnode;
718e3744 4116
4117 /* Set default weight. */
4118 if (peer_group_active (peer))
4119 peer->weight = peer->group->conf->weight;
4120 else
4121 peer->weight = 0;
4122
4123 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
4124
4125 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
ffd0c037 4126 return;
718e3744 4127
4128 /* peer-group member updates. */
4129 group = peer->group;
1eb8ef25 4130 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4131 {
4132 peer->weight = 0;
4133 }
ffd0c037 4134 return;
718e3744 4135}
6b0655a2 4136
718e3744 4137int
4138peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
4139{
4140 struct peer_group *group;
1eb8ef25 4141 struct listnode *node, *nnode;
718e3744 4142
4143 /* Not for peer group memeber. */
4144 if (peer_group_active (peer))
4145 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4146
4147 /* keepalive value check. */
4148 if (keepalive > 65535)
4149 return BGP_ERR_INVALID_VALUE;
4150
4151 /* Holdtime value check. */
4152 if (holdtime > 65535)
4153 return BGP_ERR_INVALID_VALUE;
4154
4155 /* Holdtime value must be either 0 or greater than 3. */
4156 if (holdtime < 3 && holdtime != 0)
4157 return BGP_ERR_INVALID_VALUE;
4158
4159 /* Set value to the configuration. */
4160 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4161 peer->holdtime = holdtime;
4162 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4163
4164 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4165 return 0;
4166
4167 /* peer-group member updates. */
4168 group = peer->group;
1eb8ef25 4169 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4170 {
4171 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4172 peer->holdtime = group->conf->holdtime;
4173 peer->keepalive = group->conf->keepalive;
4174 }
4175 return 0;
4176}
4177
4178int
4179peer_timers_unset (struct peer *peer)
4180{
4181 struct peer_group *group;
1eb8ef25 4182 struct listnode *node, *nnode;
718e3744 4183
4184 if (peer_group_active (peer))
4185 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4186
4187 /* Clear configuration. */
4188 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4189 peer->keepalive = 0;
4190 peer->holdtime = 0;
4191
4192 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4193 return 0;
4194
4195 /* peer-group member updates. */
4196 group = peer->group;
1eb8ef25 4197 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4198 {
4199 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4200 peer->holdtime = 0;
4201 peer->keepalive = 0;
4202 }
4203
4204 return 0;
4205}
6b0655a2 4206
718e3744 4207int
4208peer_timers_connect_set (struct peer *peer, u_int32_t connect)
4209{
966f821c
DS
4210 struct peer_group *group;
4211 struct listnode *node, *nnode;
4212
718e3744 4213 if (peer_group_active (peer))
4214 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4215
4216 if (connect > 65535)
4217 return BGP_ERR_INVALID_VALUE;
4218
4219 /* Set value to the configuration. */
4220 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4221 peer->connect = connect;
4222
4223 /* Set value to timer setting. */
4224 peer->v_connect = connect;
4225
966f821c
DS
4226 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4227 return 0;
4228
4229 /* peer-group member updates. */
4230 group = peer->group;
4231 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4232 {
4233 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4234 peer->connect = connect;
4235 peer->v_connect = connect;
4236 }
718e3744 4237 return 0;
4238}
4239
4240int
4241peer_timers_connect_unset (struct peer *peer)
4242{
966f821c
DS
4243 struct peer_group *group;
4244 struct listnode *node, *nnode;
4245
718e3744 4246 if (peer_group_active (peer))
4247 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4248
4249 /* Clear configuration. */
4250 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4251 peer->connect = 0;
4252
4253 /* Set timer setting to default value. */
4254 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4255
966f821c
DS
4256 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4257 return 0;
4258
4259 /* peer-group member updates. */
4260 group = peer->group;
4261 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4262 {
4263 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4264 peer->connect = 0;
4265 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4266 }
718e3744 4267 return 0;
4268}
6b0655a2 4269
718e3744 4270int
4271peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
4272{
966f821c
DS
4273 struct peer_group *group;
4274 struct listnode *node, *nnode;
4275
718e3744 4276 if (peer_group_active (peer))
4277 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4278
4279 if (routeadv > 600)
4280 return BGP_ERR_INVALID_VALUE;
4281
4282 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4283 peer->routeadv = routeadv;
4284 peer->v_routeadv = routeadv;
4285
3f9c7369
DS
4286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4287 update_group_adjust_peer_afs (peer);
4288 if (peer->status == Established)
4289 bgp_announce_route_all (peer);
966f821c 4290 return 0;
3f9c7369 4291 }
966f821c
DS
4292
4293 /* peer-group member updates. */
4294 group = peer->group;
4295 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4296 {
4297 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4298 peer->routeadv = routeadv;
4299 peer->v_routeadv = routeadv;
3f9c7369
DS
4300 update_group_adjust_peer_afs (peer);
4301 if (peer->status == Established)
4302 bgp_announce_route_all (peer);
966f821c
DS
4303 }
4304
718e3744 4305 return 0;
4306}
4307
4308int
4309peer_advertise_interval_unset (struct peer *peer)
4310{
966f821c
DS
4311 struct peer_group *group;
4312 struct listnode *node, *nnode;
4313
718e3744 4314 if (peer_group_active (peer))
4315 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4316
4317 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4318 peer->routeadv = 0;
4319
6d85b15b 4320 if (peer->sort == BGP_PEER_IBGP)
718e3744 4321 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4322 else
4323 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
966f821c 4324
3f9c7369
DS
4325 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4326 update_group_adjust_peer_afs (peer);
4327 if (peer->status == Established)
4328 bgp_announce_route_all (peer);
966f821c 4329 return 0;
3f9c7369 4330 }
966f821c
DS
4331
4332 /* peer-group member updates. */
4333 group = peer->group;
4334 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4335 {
4336 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4337 peer->routeadv = 0;
4338
4339 if (peer->sort == BGP_PEER_IBGP)
4340 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4341 else
4342 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3f9c7369
DS
4343
4344 update_group_adjust_peer_afs (peer);
4345 if (peer->status == Established)
4346 bgp_announce_route_all (peer);
966f821c 4347 }
718e3744 4348
4349 return 0;
4350}
6b0655a2 4351
718e3744 4352/* neighbor interface */
ffd0c037 4353void
fd79ac91 4354peer_interface_set (struct peer *peer, const char *str)
718e3744 4355{
4356 if (peer->ifname)
4357 free (peer->ifname);
4358 peer->ifname = strdup (str);
718e3744 4359}
4360
ffd0c037 4361void
718e3744 4362peer_interface_unset (struct peer *peer)
4363{
4364 if (peer->ifname)
4365 free (peer->ifname);
4366 peer->ifname = NULL;
718e3744 4367}
6b0655a2 4368
718e3744 4369/* Allow-as in. */
4370int
4371peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
4372{
4373 struct peer_group *group;
1eb8ef25 4374 struct listnode *node, *nnode;
718e3744 4375
4376 if (allow_num < 1 || allow_num > 10)
4377 return BGP_ERR_INVALID_VALUE;
4378
4379 if (peer->allowas_in[afi][safi] != allow_num)
4380 {
4381 peer->allowas_in[afi][safi] = allow_num;
4382 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
4383 peer_change_action (peer, afi, safi, peer_change_reset_in);
4384 }
4385
4386 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4387 return 0;
4388
4389 group = peer->group;
1eb8ef25 4390 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4391 {
4392 if (peer->allowas_in[afi][safi] != allow_num)
4393 {
4394 peer->allowas_in[afi][safi] = allow_num;
4395 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
4396 peer_change_action (peer, afi, safi, peer_change_reset_in);
4397 }
4398
4399 }
4400 return 0;
4401}
4402
4403int
4404peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
4405{
4406 struct peer_group *group;
1eb8ef25 4407 struct listnode *node, *nnode;
718e3744 4408
4409 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4410 {
4411 peer->allowas_in[afi][safi] = 0;
4412 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4413 }
4414
4415 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4416 return 0;
4417
4418 group = peer->group;
1eb8ef25 4419 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4420 {
4421 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4422 {
4423 peer->allowas_in[afi][safi] = 0;
4424 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4425 }
4426 }
4427 return 0;
4428}
6b0655a2 4429
718e3744 4430int
9d3f9705 4431peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
718e3744 4432{
4433 struct bgp *bgp = peer->bgp;
4434 struct peer_group *group;
1eb8ef25 4435 struct listnode *node, *nnode;
718e3744 4436
4437 if (peer_sort (peer) != BGP_PEER_EBGP
4438 && peer_sort (peer) != BGP_PEER_INTERNAL)
4439 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4440
4441 if (bgp->as == as)
4442 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4443
4444 if (peer_group_active (peer))
4445 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4446
9d3f9705
AC
4447 if (peer->as == as)
4448 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4449
718e3744 4450 if (peer->change_local_as == as &&
4451 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
9d3f9705
AC
4452 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
4453 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
4454 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
718e3744 4455 return 0;
4456
4457 peer->change_local_as = as;
4458 if (no_prepend)
4459 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4460 else
4461 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4462
9d3f9705
AC
4463 if (replace_as)
4464 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4465 else
4466 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4467
718e3744 4468 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4469 {
6aa136f1 4470 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4471 {
4472 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4473 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4474 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4475 }
718e3744 4476 else
1ff9a340 4477 bgp_session_reset(peer);
718e3744 4478 return 0;
4479 }
4480
4481 group = peer->group;
1eb8ef25 4482 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4483 {
4484 peer->change_local_as = as;
4485 if (no_prepend)
4486 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4487 else
4488 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4489
9d3f9705
AC
4490 if (replace_as)
4491 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4492 else
4493 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4494
6aa136f1 4495 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4496 {
4497 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4498 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4499 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4500 }
718e3744 4501 else
4502 BGP_EVENT_ADD (peer, BGP_Stop);
4503 }
4504
4505 return 0;
4506}
4507
4508int
4509peer_local_as_unset (struct peer *peer)
4510{
4511 struct peer_group *group;
1eb8ef25 4512 struct listnode *node, *nnode;
718e3744 4513
4514 if (peer_group_active (peer))
4515 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4516
4517 if (! peer->change_local_as)
4518 return 0;
4519
4520 peer->change_local_as = 0;
4521 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4522 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4523
4524 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4525 {
6aa136f1 4526 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4527 {
4528 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4529 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4530 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4531 }
718e3744 4532 else
4533 BGP_EVENT_ADD (peer, BGP_Stop);
4534
4535 return 0;
4536 }
4537
4538 group = peer->group;
1eb8ef25 4539 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4540 {
4541 peer->change_local_as = 0;
4542 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4543 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4544
6aa136f1 4545 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4546 {
4547 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4548 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4549 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4550 }
718e3744 4551 else
1ff9a340 4552 bgp_session_reset(peer);
718e3744 4553 }
4554 return 0;
4555}
6b0655a2 4556
0df7c91f
PJ
4557/* Set password for authenticating with the peer. */
4558int
4559peer_password_set (struct peer *peer, const char *password)
4560{
4561 struct listnode *nn, *nnode;
4562 int len = password ? strlen(password) : 0;
4563 int ret = BGP_SUCCESS;
4564
4565 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
4566 return BGP_ERR_INVALID_VALUE;
4567
4568 if (peer->password && strcmp (peer->password, password) == 0
4569 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4570 return 0;
4571
4572 if (peer->password)
4573 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4574
4575 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
4576
4577 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4578 {
6aa136f1
VS
4579 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4580 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
0df7c91f 4581 else
1ff9a340 4582 bgp_session_reset(peer);
0df7c91f
PJ
4583
4584 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
4585 }
4586
4587 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
4588 {
4589 if (peer->password && strcmp (peer->password, password) == 0)
4590 continue;
4591
4592 if (peer->password)
4593 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4594
4595 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4596
6aa136f1 4597 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4598 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4599 else
1ff9a340 4600 bgp_session_reset(peer);
0df7c91f
PJ
4601
4602 if (bgp_md5_set (peer) < 0)
4603 ret = BGP_ERR_TCPSIG_FAILED;
4604 }
4605
4606 return ret;
4607}
4608
4609int
4610peer_password_unset (struct peer *peer)
4611{
4612 struct listnode *nn, *nnode;
4613
4614 if (!peer->password
4615 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4616 return 0;
4617
4618 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4619 {
4620 if (peer_group_active (peer)
4621 && peer->group->conf->password
4622 && strcmp (peer->group->conf->password, peer->password) == 0)
4623 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
4624
6aa136f1 4625 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4626 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4627 else
1ff9a340 4628 bgp_session_reset(peer);
0df7c91f
PJ
4629
4630 if (peer->password)
4631 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4632
4633 peer->password = NULL;
4634
4635 bgp_md5_set (peer);
4636
4637 return 0;
4638 }
4639
4640 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4641 peer->password = NULL;
4642
4643 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
4644 {
4645 if (!peer->password)
4646 continue;
4647
6aa136f1 4648 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4649 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4650 else
1ff9a340 4651 bgp_session_reset(peer);
0df7c91f
PJ
4652
4653 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4654 peer->password = NULL;
4655
4656 bgp_md5_set (peer);
4657 }
4658
4659 return 0;
4660}
6b0655a2 4661
3f9c7369 4662/*
3f9c7369 4663 * Helper function that is called after the name of the policy
94f34286
DS
4664 * being used by a peer has changed (AF specific). Automatically
4665 * initiates inbound or outbound processing as needed.
3f9c7369
DS
4666 */
4667static void
94f34286 4668peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
3f9c7369 4669{
94f34286 4670 if (outbound)
3f9c7369 4671 {
94f34286
DS
4672 update_group_adjust_peer (peer_af_find (peer, afi, safi));
4673 if (peer->status == Established)
4674 bgp_announce_route(peer, afi, safi);
3f9c7369
DS
4675 }
4676 else
94f34286
DS
4677 {
4678 if (peer->status != Established)
4679 return;
4680
4681 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4682 bgp_soft_reconfig_in (peer, afi, safi);
4683 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4684 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4685 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4686 }
3f9c7369
DS
4687}
4688
4689
718e3744 4690/* Set distribute list to the peer. */
4691int
4692peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 4693 const char *name)
718e3744 4694{
4695 struct bgp_filter *filter;
4696 struct peer_group *group;
1eb8ef25 4697 struct listnode *node, *nnode;
718e3744 4698
4699 if (! peer->afc[afi][safi])
4700 return BGP_ERR_PEER_INACTIVE;
4701
4702 if (direct != FILTER_IN && direct != FILTER_OUT)
4703 return BGP_ERR_INVALID_VALUE;
4704
4705 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4706 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4707
4708 filter = &peer->filter[afi][safi];
4709
4710 if (filter->plist[direct].name)
4711 return BGP_ERR_PEER_FILTER_CONFLICT;
4712
4713 if (filter->dlist[direct].name)
4714 free (filter->dlist[direct].name);
4715 filter->dlist[direct].name = strdup (name);
4716 filter->dlist[direct].alist = access_list_lookup (afi, name);
4717
4718 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4719 {
94f34286
DS
4720 peer_on_policy_change(peer, afi, safi,
4721 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4722 return 0;
4723 }
718e3744 4724
4725 group = peer->group;
1eb8ef25 4726 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4727 {
4728 filter = &peer->filter[afi][safi];
4729
4730 if (! peer->af_group[afi][safi])
4731 continue;
4732
4733 if (filter->dlist[direct].name)
4734 free (filter->dlist[direct].name);
4735 filter->dlist[direct].name = strdup (name);
4736 filter->dlist[direct].alist = access_list_lookup (afi, name);
94f34286
DS
4737 peer_on_policy_change(peer, afi, safi,
4738 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4739 }
4740
4741 return 0;
4742}
4743
4744int
4745peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4746{
4747 struct bgp_filter *filter;
4748 struct bgp_filter *gfilter;
4749 struct peer_group *group;
1eb8ef25 4750 struct listnode *node, *nnode;
718e3744 4751
4752 if (! peer->afc[afi][safi])
4753 return BGP_ERR_PEER_INACTIVE;
4754
4755 if (direct != FILTER_IN && direct != FILTER_OUT)
4756 return BGP_ERR_INVALID_VALUE;
4757
4758 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4759 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4760
4761 filter = &peer->filter[afi][safi];
4762
4763 /* apply peer-group filter */
4764 if (peer->af_group[afi][safi])
4765 {
4766 gfilter = &peer->group->conf->filter[afi][safi];
4767
4768 if (gfilter->dlist[direct].name)
4769 {
4770 if (filter->dlist[direct].name)
4771 free (filter->dlist[direct].name);
4772 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
4773 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
94f34286
DS
4774 peer_on_policy_change(peer, afi, safi,
4775 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4776 return 0;
4777 }
4778 }
4779
4780 if (filter->dlist[direct].name)
4781 free (filter->dlist[direct].name);
4782 filter->dlist[direct].name = NULL;
4783 filter->dlist[direct].alist = NULL;
4784
4785 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4786 {
94f34286
DS
4787 peer_on_policy_change(peer, afi, safi,
4788 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4789 return 0;
4790 }
718e3744 4791
94f34286
DS
4792 group = peer->group;
4793 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4794 {
4795 filter = &peer->filter[afi][safi];
718e3744 4796
94f34286
DS
4797 if (! peer->af_group[afi][safi])
4798 continue;
718e3744 4799
94f34286
DS
4800 if (filter->dlist[direct].name)
4801 free (filter->dlist[direct].name);
4802 filter->dlist[direct].name = NULL;
4803 filter->dlist[direct].alist = NULL;
4804 peer_on_policy_change(peer, afi, safi,
4805 (direct == FILTER_OUT) ? 1 : 0);
4806 }
718e3744 4807
4808 return 0;
4809}
4810
4811/* Update distribute list. */
94f2b392 4812static void
718e3744 4813peer_distribute_update (struct access_list *access)
4814{
4815 afi_t afi;
4816 safi_t safi;
4817 int direct;
1eb8ef25 4818 struct listnode *mnode, *mnnode;
4819 struct listnode *node, *nnode;
718e3744 4820 struct bgp *bgp;
4821 struct peer *peer;
4822 struct peer_group *group;
4823 struct bgp_filter *filter;
4824
1eb8ef25 4825 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 4826 {
3f9c7369
DS
4827 if (access->name)
4828 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name,
4829 0, 0);
1eb8ef25 4830 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 4831 {
4832 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4833 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4834 {
4835 filter = &peer->filter[afi][safi];
4836
4837 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4838 {
4839 if (filter->dlist[direct].name)
4840 filter->dlist[direct].alist =
4841 access_list_lookup (afi, filter->dlist[direct].name);
4842 else
4843 filter->dlist[direct].alist = NULL;
4844 }
4845 }
4846 }
1eb8ef25 4847 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 4848 {
4849 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4850 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4851 {
4852 filter = &group->conf->filter[afi][safi];
4853
4854 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4855 {
4856 if (filter->dlist[direct].name)
4857 filter->dlist[direct].alist =
4858 access_list_lookup (afi, filter->dlist[direct].name);
4859 else
4860 filter->dlist[direct].alist = NULL;
4861 }
4862 }
4863 }
4864 }
4865}
6b0655a2 4866
718e3744 4867/* Set prefix list to the peer. */
4868int
4869peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 4870 const char *name)
718e3744 4871{
4872 struct bgp_filter *filter;
4873 struct peer_group *group;
1eb8ef25 4874 struct listnode *node, *nnode;
718e3744 4875
4876 if (! peer->afc[afi][safi])
4877 return BGP_ERR_PEER_INACTIVE;
4878
4879 if (direct != FILTER_IN && direct != FILTER_OUT)
4880 return BGP_ERR_INVALID_VALUE;
4881
4882 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4883 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4884
4885 filter = &peer->filter[afi][safi];
4886
4887 if (filter->dlist[direct].name)
4888 return BGP_ERR_PEER_FILTER_CONFLICT;
4889
4890 if (filter->plist[direct].name)
4891 free (filter->plist[direct].name);
4892 filter->plist[direct].name = strdup (name);
4893 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4894
4895 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4896 {
94f34286
DS
4897 peer_on_policy_change(peer, afi, safi,
4898 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4899 return 0;
4900 }
718e3744 4901
4902 group = peer->group;
1eb8ef25 4903 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4904 {
4905 filter = &peer->filter[afi][safi];
4906
4907 if (! peer->af_group[afi][safi])
4908 continue;
4909
4910 if (filter->plist[direct].name)
4911 free (filter->plist[direct].name);
4912 filter->plist[direct].name = strdup (name);
4913 filter->plist[direct].plist = prefix_list_lookup (afi, name);
94f34286
DS
4914 peer_on_policy_change(peer, afi, safi,
4915 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4916 }
4917 return 0;
4918}
4919
4920int
4921peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4922{
4923 struct bgp_filter *filter;
4924 struct bgp_filter *gfilter;
4925 struct peer_group *group;
1eb8ef25 4926 struct listnode *node, *nnode;
718e3744 4927
4928 if (! peer->afc[afi][safi])
4929 return BGP_ERR_PEER_INACTIVE;
4930
4931 if (direct != FILTER_IN && direct != FILTER_OUT)
4932 return BGP_ERR_INVALID_VALUE;
4933
4934 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4935 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4936
4937 filter = &peer->filter[afi][safi];
4938
4939 /* apply peer-group filter */
4940 if (peer->af_group[afi][safi])
4941 {
4942 gfilter = &peer->group->conf->filter[afi][safi];
4943
4944 if (gfilter->plist[direct].name)
4945 {
4946 if (filter->plist[direct].name)
4947 free (filter->plist[direct].name);
4948 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4949 filter->plist[direct].plist = gfilter->plist[direct].plist;
94f34286
DS
4950 peer_on_policy_change(peer, afi, safi,
4951 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4952 return 0;
4953 }
4954 }
4955
4956 if (filter->plist[direct].name)
4957 free (filter->plist[direct].name);
4958 filter->plist[direct].name = NULL;
4959 filter->plist[direct].plist = NULL;
4960
4961 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4962 {
94f34286
DS
4963 peer_on_policy_change(peer, afi, safi,
4964 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4965 return 0;
4966 }
718e3744 4967
4968 group = peer->group;
1eb8ef25 4969 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4970 {
4971 filter = &peer->filter[afi][safi];
4972
4973 if (! peer->af_group[afi][safi])
4974 continue;
4975
4976 if (filter->plist[direct].name)
4977 free (filter->plist[direct].name);
4978 filter->plist[direct].name = NULL;
4979 filter->plist[direct].plist = NULL;
94f34286
DS
4980 peer_on_policy_change(peer, afi, safi,
4981 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4982 }
4983
4984 return 0;
4985}
4986
4987/* Update prefix-list list. */
94f2b392 4988static void
718e3744 4989peer_prefix_list_update (struct prefix_list *plist)
4990{
1eb8ef25 4991 struct listnode *mnode, *mnnode;
4992 struct listnode *node, *nnode;
718e3744 4993 struct bgp *bgp;
4994 struct peer *peer;
4995 struct peer_group *group;
4996 struct bgp_filter *filter;
4997 afi_t afi;
4998 safi_t safi;
4999 int direct;
5000
1eb8ef25 5001 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5002 {
3f9c7369
DS
5003
5004 /*
5005 * Update the prefix-list on update groups.
5006 */
5007 update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST,
5008 plist ? plist->name : NULL, 0, 0);
5009
1eb8ef25 5010 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5011 {
5012 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5013 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5014 {
5015 filter = &peer->filter[afi][safi];
5016
5017 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5018 {
5019 if (filter->plist[direct].name)
5020 filter->plist[direct].plist =
5021 prefix_list_lookup (afi, filter->plist[direct].name);
5022 else
5023 filter->plist[direct].plist = NULL;
5024 }
5025 }
5026 }
1eb8ef25 5027 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5028 {
5029 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5030 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5031 {
5032 filter = &group->conf->filter[afi][safi];
5033
5034 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5035 {
5036 if (filter->plist[direct].name)
5037 filter->plist[direct].plist =
5038 prefix_list_lookup (afi, filter->plist[direct].name);
5039 else
5040 filter->plist[direct].plist = NULL;
5041 }
5042 }
5043 }
5044 }
5045}
6b0655a2 5046
718e3744 5047int
5048peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5049 const char *name)
718e3744 5050{
5051 struct bgp_filter *filter;
5052 struct peer_group *group;
1eb8ef25 5053 struct listnode *node, *nnode;
718e3744 5054
5055 if (! peer->afc[afi][safi])
5056 return BGP_ERR_PEER_INACTIVE;
5057
5058 if (direct != FILTER_IN && direct != FILTER_OUT)
5059 return BGP_ERR_INVALID_VALUE;
5060
5061 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
5062 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5063
5064 filter = &peer->filter[afi][safi];
5065
5066 if (filter->aslist[direct].name)
5067 free (filter->aslist[direct].name);
5068 filter->aslist[direct].name = strdup (name);
5069 filter->aslist[direct].aslist = as_list_lookup (name);
5070
5071 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5072 {
94f34286
DS
5073 peer_on_policy_change(peer, afi, safi,
5074 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5075 return 0;
5076 }
718e3744 5077
5078 group = peer->group;
1eb8ef25 5079 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5080 {
5081 filter = &peer->filter[afi][safi];
5082
5083 if (! peer->af_group[afi][safi])
5084 continue;
5085
5086 if (filter->aslist[direct].name)
5087 free (filter->aslist[direct].name);
5088 filter->aslist[direct].name = strdup (name);
5089 filter->aslist[direct].aslist = as_list_lookup (name);
94f34286
DS
5090 peer_on_policy_change(peer, afi, safi,
5091 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5092 }
5093 return 0;
5094}
5095
5096int
5097peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
5098{
5099 struct bgp_filter *filter;
5100 struct bgp_filter *gfilter;
5101 struct peer_group *group;
1eb8ef25 5102 struct listnode *node, *nnode;
718e3744 5103
5104 if (! peer->afc[afi][safi])
5105 return BGP_ERR_PEER_INACTIVE;
5106
b5f29603 5107 if (direct != FILTER_IN && direct != FILTER_OUT)
718e3744 5108 return BGP_ERR_INVALID_VALUE;
5109
b5f29603 5110 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
718e3744 5111 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5112
5113 filter = &peer->filter[afi][safi];
5114
5115 /* apply peer-group filter */
5116 if (peer->af_group[afi][safi])
5117 {
5118 gfilter = &peer->group->conf->filter[afi][safi];
5119
5120 if (gfilter->aslist[direct].name)
5121 {
5122 if (filter->aslist[direct].name)
5123 free (filter->aslist[direct].name);
5124 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
5125 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
94f34286
DS
5126 peer_on_policy_change(peer, afi, safi,
5127 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5128 return 0;
5129 }
5130 }
5131
5132 if (filter->aslist[direct].name)
5133 free (filter->aslist[direct].name);
5134 filter->aslist[direct].name = NULL;
5135 filter->aslist[direct].aslist = NULL;
5136
5137 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5138 {
94f34286
DS
5139 peer_on_policy_change(peer, afi, safi,
5140 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5141 return 0;
5142 }
718e3744 5143
5144 group = peer->group;
1eb8ef25 5145 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5146 {
5147 filter = &peer->filter[afi][safi];
5148
5149 if (! peer->af_group[afi][safi])
5150 continue;
5151
5152 if (filter->aslist[direct].name)
5153 free (filter->aslist[direct].name);
5154 filter->aslist[direct].name = NULL;
5155 filter->aslist[direct].aslist = NULL;
94f34286
DS
5156 peer_on_policy_change(peer, afi, safi,
5157 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5158 }
5159
5160 return 0;
5161}
5162
94f2b392 5163static void
ffd0c037 5164peer_aslist_update (const char *aslist_name)
718e3744 5165{
5166 afi_t afi;
5167 safi_t safi;
5168 int direct;
1eb8ef25 5169 struct listnode *mnode, *mnnode;
5170 struct listnode *node, *nnode;
718e3744 5171 struct bgp *bgp;
5172 struct peer *peer;
5173 struct peer_group *group;
5174 struct bgp_filter *filter;
5175
1eb8ef25 5176 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5177 {
3f9c7369
DS
5178 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name,
5179 0, 0);
5180
1eb8ef25 5181 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5182 {
5183 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5184 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5185 {
5186 filter = &peer->filter[afi][safi];
5187
5188 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5189 {
5190 if (filter->aslist[direct].name)
5191 filter->aslist[direct].aslist =
5192 as_list_lookup (filter->aslist[direct].name);
5193 else
5194 filter->aslist[direct].aslist = NULL;
5195 }
5196 }
5197 }
1eb8ef25 5198 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5199 {
5200 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5201 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5202 {
5203 filter = &group->conf->filter[afi][safi];
5204
5205 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5206 {
5207 if (filter->aslist[direct].name)
5208 filter->aslist[direct].aslist =
5209 as_list_lookup (filter->aslist[direct].name);
5210 else
5211 filter->aslist[direct].aslist = NULL;
5212 }
5213 }
5214 }
5215 }
5216}
3f9c7369 5217
518f0eb1
DS
5218static void
5219peer_aslist_add (char *aslist_name)
5220{
5221 peer_aslist_update (aslist_name);
5222 route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED);
5223}
5224
5225static void
ffd0c037 5226peer_aslist_del (const char *aslist_name)
518f0eb1
DS
5227{
5228 peer_aslist_update (aslist_name);
ffd0c037 5229 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
518f0eb1
DS
5230}
5231
6b0655a2 5232
718e3744 5233int
5234peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5235 const char *name)
718e3744 5236{
5237 struct bgp_filter *filter;
5238 struct peer_group *group;
1eb8ef25 5239 struct listnode *node, *nnode;
718e3744 5240
5241 if (! peer->afc[afi][safi])
5242 return BGP_ERR_PEER_INACTIVE;
5243
fee0f4c6 5244 if (direct != RMAP_IN && direct != RMAP_OUT &&
5245 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
718e3744 5246 return BGP_ERR_INVALID_VALUE;
5247
fee0f4c6 5248 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
5249 && peer_is_group_member (peer, afi, safi))
718e3744 5250 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5251
5252 filter = &peer->filter[afi][safi];
5253
5254 if (filter->map[direct].name)
5255 free (filter->map[direct].name);
518f0eb1 5256
718e3744 5257 filter->map[direct].name = strdup (name);
5258 filter->map[direct].map = route_map_lookup_by_name (name);
5259
5260 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5261 {
94f34286
DS
5262 peer_on_policy_change(peer, afi, safi,
5263 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5264 return 0;
5265 }
718e3744 5266
5267 group = peer->group;
1eb8ef25 5268 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5269 {
5270 filter = &peer->filter[afi][safi];
5271
5272 if (! peer->af_group[afi][safi])
5273 continue;
5274
5275 if (filter->map[direct].name)
5276 free (filter->map[direct].name);
5277 filter->map[direct].name = strdup (name);
5278 filter->map[direct].map = route_map_lookup_by_name (name);
94f34286
DS
5279 peer_on_policy_change(peer, afi, safi,
5280 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5281 }
5282 return 0;
5283}
5284
5285/* Unset route-map from the peer. */
5286int
5287peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5288{
5289 struct bgp_filter *filter;
5290 struct bgp_filter *gfilter;
5291 struct peer_group *group;
1eb8ef25 5292 struct listnode *node, *nnode;
718e3744 5293
5294 if (! peer->afc[afi][safi])
5295 return BGP_ERR_PEER_INACTIVE;
5296
b5f29603 5297 if (direct != RMAP_IN && direct != RMAP_OUT &&
5298 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
718e3744 5299 return BGP_ERR_INVALID_VALUE;
5300
b5f29603 5301 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
5302 && peer_is_group_member (peer, afi, safi))
718e3744 5303 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5304
5305 filter = &peer->filter[afi][safi];
5306
5307 /* apply peer-group filter */
5308 if (peer->af_group[afi][safi])
5309 {
5310 gfilter = &peer->group->conf->filter[afi][safi];
5311
5312 if (gfilter->map[direct].name)
5313 {
5314 if (filter->map[direct].name)
5315 free (filter->map[direct].name);
5316 filter->map[direct].name = strdup (gfilter->map[direct].name);
5317 filter->map[direct].map = gfilter->map[direct].map;
94f34286
DS
5318 peer_on_policy_change(peer, afi, safi,
5319 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5320 return 0;
5321 }
5322 }
5323
5324 if (filter->map[direct].name)
5325 free (filter->map[direct].name);
5326 filter->map[direct].name = NULL;
5327 filter->map[direct].map = NULL;
5328
5329 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5330 {
94f34286
DS
5331 peer_on_policy_change(peer, afi, safi,
5332 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5333 return 0;
5334 }
718e3744 5335
5336 group = peer->group;
1eb8ef25 5337 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5338 {
5339 filter = &peer->filter[afi][safi];
5340
5341 if (! peer->af_group[afi][safi])
5342 continue;
5343
5344 if (filter->map[direct].name)
5345 free (filter->map[direct].name);
5346 filter->map[direct].name = NULL;
5347 filter->map[direct].map = NULL;
94f34286
DS
5348 peer_on_policy_change(peer, afi, safi,
5349 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5350 }
5351 return 0;
5352}
6b0655a2 5353
718e3744 5354/* Set unsuppress-map to the peer. */
5355int
fd79ac91 5356peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
5357 const char *name)
718e3744 5358{
5359 struct bgp_filter *filter;
5360 struct peer_group *group;
1eb8ef25 5361 struct listnode *node, *nnode;
718e3744 5362
5363 if (! peer->afc[afi][safi])
5364 return BGP_ERR_PEER_INACTIVE;
5365
5366 if (peer_is_group_member (peer, afi, safi))
5367 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5368
5369 filter = &peer->filter[afi][safi];
5370
5371 if (filter->usmap.name)
5372 free (filter->usmap.name);
5373
5374 filter->usmap.name = strdup (name);
5375 filter->usmap.map = route_map_lookup_by_name (name);
5376
5377 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5378 {
94f34286 5379 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5380 return 0;
5381 }
718e3744 5382
5383 group = peer->group;
1eb8ef25 5384 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5385 {
5386 filter = &peer->filter[afi][safi];
5387
5388 if (! peer->af_group[afi][safi])
5389 continue;
5390
5391 if (filter->usmap.name)
5392 free (filter->usmap.name);
5393 filter->usmap.name = strdup (name);
5394 filter->usmap.map = route_map_lookup_by_name (name);
94f34286 5395 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5396 }
5397 return 0;
5398}
5399
5400/* Unset route-map from the peer. */
5401int
5402peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
5403{
5404 struct bgp_filter *filter;
5405 struct peer_group *group;
1eb8ef25 5406 struct listnode *node, *nnode;
718e3744 5407
5408 if (! peer->afc[afi][safi])
5409 return BGP_ERR_PEER_INACTIVE;
5410
5411 if (peer_is_group_member (peer, afi, safi))
5412 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5413
5414 filter = &peer->filter[afi][safi];
5415
5416 if (filter->usmap.name)
5417 free (filter->usmap.name);
5418 filter->usmap.name = NULL;
5419 filter->usmap.map = NULL;
5420
5421 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5422 {
94f34286 5423 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5424 return 0;
5425 }
718e3744 5426
5427 group = peer->group;
1eb8ef25 5428 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5429 {
5430 filter = &peer->filter[afi][safi];
5431
5432 if (! peer->af_group[afi][safi])
5433 continue;
5434
5435 if (filter->usmap.name)
5436 free (filter->usmap.name);
5437 filter->usmap.name = NULL;
5438 filter->usmap.map = NULL;
94f34286 5439 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5440 }
5441 return 0;
5442}
6b0655a2 5443
718e3744 5444int
5445peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
0a486e5f 5446 u_int32_t max, u_char threshold,
5447 int warning, u_int16_t restart)
718e3744 5448{
5449 struct peer_group *group;
1eb8ef25 5450 struct listnode *node, *nnode;
718e3744 5451
5452 if (! peer->afc[afi][safi])
5453 return BGP_ERR_PEER_INACTIVE;
5454
5455 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5456 peer->pmax[afi][safi] = max;
e0701b79 5457 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 5458 peer->pmax_restart[afi][safi] = restart;
718e3744 5459 if (warning)
5460 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5461 else
5462 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5463
fc9a856f 5464 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
718e3744 5465 {
fc9a856f
DS
5466 group = peer->group;
5467 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5468 {
5469 if (! peer->af_group[afi][safi])
5470 continue;
718e3744 5471
fc9a856f
DS
5472 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5473 peer->pmax[afi][safi] = max;
5474 peer->pmax_threshold[afi][safi] = threshold;
5475 peer->pmax_restart[afi][safi] = restart;
5476 if (warning)
5477 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5478 else
5479 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5480
5481 if ((peer->status == Established) && (peer->afc[afi][safi]))
5482 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
5483 }
5484 }
5485 else
5486 {
5487 if ((peer->status == Established) && (peer->afc[afi][safi]))
5488 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
718e3744 5489 }
fc9a856f 5490
718e3744 5491 return 0;
5492}
5493
5494int
5495peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
5496{
5497 struct peer_group *group;
1eb8ef25 5498 struct listnode *node, *nnode;
718e3744 5499
5500 if (! peer->afc[afi][safi])
5501 return BGP_ERR_PEER_INACTIVE;
5502
5503 /* apply peer-group config */
5504 if (peer->af_group[afi][safi])
5505 {
5506 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5507 PEER_FLAG_MAX_PREFIX))
5508 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5509 else
5510 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5511
5512 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5513 PEER_FLAG_MAX_PREFIX_WARNING))
5514 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5515 else
5516 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5517
5518 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
e0701b79 5519 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
0a486e5f 5520 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
718e3744 5521 return 0;
5522 }
5523
5524 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5525 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5526 peer->pmax[afi][safi] = 0;
0a486e5f 5527 peer->pmax_threshold[afi][safi] = 0;
5528 peer->pmax_restart[afi][safi] = 0;
718e3744 5529
5530 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5531 return 0;
5532
5533 group = peer->group;
1eb8ef25 5534 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5535 {
5536 if (! peer->af_group[afi][safi])
5537 continue;
5538
5539 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5540 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5541 peer->pmax[afi][safi] = 0;
0a486e5f 5542 peer->pmax_threshold[afi][safi] = 0;
5543 peer->pmax_restart[afi][safi] = 0;
718e3744 5544 }
5545 return 0;
5546}
5f9adb5d 5547
c43ed2e4 5548int is_ebgp_multihop_configured (struct peer *peer)
5f9adb5d
DL
5549{
5550 struct peer_group *group;
5551 struct listnode *node, *nnode;
5552 struct peer *peer1;
5553
5554 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5555 {
5556 group = peer->group;
5d804b43
PM
5557 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5558 (group->conf->ttl != 1))
5f9adb5d
DL
5559 return 1;
5560
5561 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
5562 {
5d804b43
PM
5563 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
5564 (peer1->ttl != 1))
5f9adb5d
DL
5565 return 1;
5566 }
5567 }
5568 else
5569 {
5d804b43
PM
5570 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5571 (peer->ttl != 1))
5f9adb5d
DL
5572 return 1;
5573 }
5574 return 0;
5575}
5576
fa411a21
NH
5577/* Set # of hops between us and BGP peer. */
5578int
5579peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
5580{
5581 struct peer_group *group;
5582 struct listnode *node, *nnode;
fa411a21
NH
5583 int ret;
5584
5585 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
5586
fa411a21
NH
5587 /* We cannot configure ttl-security hops when ebgp-multihop is already
5588 set. For non peer-groups, the check is simple. For peer-groups, it's
5589 slightly messy, because we need to check both the peer-group structure
5590 and all peer-group members for any trace of ebgp-multihop configuration
5591 before actually applying the ttl-security rules. Cisco really made a
5592 mess of this configuration parameter, and OpenBGPD got it right.
5593 */
e5cc509c
DS
5594
5595 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP))
5f9adb5d
DL
5596 {
5597 if (is_ebgp_multihop_configured (peer))
5598 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
fa411a21 5599
e5cc509c
DS
5600 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5601 {
5602 peer->gtsm_hops = gtsm_hops;
fa411a21 5603
e5cc509c
DS
5604 /* Calling ebgp multihop also resets the session.
5605 * On restart, NHT will get setup correctly as will the
5606 * min & max ttls on the socket. The return value is
5607 * irrelevant.
5608 */
5609 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5610
5611 if (ret != 0)
5612 return ret;
5613 }
5614 else
5615 {
5616 group = peer->group;
5617 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5618 {
5619 peer->gtsm_hops = group->conf->gtsm_hops;
5620
5621 /* Calling ebgp multihop also resets the session.
5622 * On restart, NHT will get setup correctly as will the
5623 * min & max ttls on the socket. The return value is
5624 * irrelevant.
5625 */
5626 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5627 }
5628 }
fa411a21
NH
5629 }
5630 else
5631 {
e5cc509c
DS
5632 /* Post the first gtsm setup or if its ibgp, maxttl setting isn't
5633 * necessary, just set the minttl.
5634 */
5635 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
fa411a21 5636 {
e5cc509c 5637 peer->gtsm_hops = gtsm_hops;
fa411a21 5638
e5cc509c
DS
5639 if (peer->fd >= 0)
5640 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5641 MAXTTL + 1 - gtsm_hops);
5642 if ((peer->status < Established) && peer->doppelganger &&
5643 (peer->doppelganger->fd >= 0))
5644 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5645 MAXTTL + 1 - gtsm_hops);
5646 }
5647 else
5648 {
5649 group = peer->group;
5650 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
f5a4827d 5651 {
e5cc509c
DS
5652 peer->gtsm_hops = group->conf->gtsm_hops;
5653
5654 /* Change setting of existing peer
5655 * established then change value (may break connectivity)
5656 * not established yet (teardown session and restart)
5657 * no session then do nothing (will get handled by next connection)
5658 */
f5a4827d
SH
5659 if (peer->fd >= 0 && peer->gtsm_hops != 0)
5660 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5661 MAXTTL + 1 - peer->gtsm_hops);
e5cc509c
DS
5662 if ((peer->status < Established) && peer->doppelganger &&
5663 (peer->doppelganger->fd >= 0))
5664 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5665 MAXTTL + 1 - gtsm_hops);
5666
f5a4827d 5667 }
fa411a21
NH
5668 }
5669 }
5670
5671 return 0;
5672}
5673
5674int
5675peer_ttl_security_hops_unset (struct peer *peer)
5676{
5677 struct peer_group *group;
5678 struct listnode *node, *nnode;
e5cc509c 5679 int ret = 0;
fa411a21
NH
5680
5681 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
5682
fa411a21
NH
5683 /* if a peer-group member, then reset to peer-group default rather than 0 */
5684 if (peer_group_active (peer))
5685 peer->gtsm_hops = peer->group->conf->gtsm_hops;
5686 else
5687 peer->gtsm_hops = 0;
5688
fa411a21
NH
5689 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5690 {
e5cc509c
DS
5691 /* Invoking ebgp_multihop_set will set the TTL back to the original
5692 * value as well as restting the NHT and such. The session is reset.
5693 */
5694 if (peer->sort == BGP_PEER_EBGP)
5695 ret = peer_ebgp_multihop_unset (peer);
5696 else
5697 {
5698 if (peer->fd >= 0)
5699 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 5700
e5cc509c
DS
5701 if ((peer->status < Established) && peer->doppelganger &&
5702 (peer->doppelganger->fd >= 0))
5703 sockopt_minttl (peer->su.sa.sa_family,
5704 peer->doppelganger->fd, 0);
5705 }
fa411a21
NH
5706 }
5707 else
5708 {
5709 group = peer->group;
5710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5711 {
fa411a21 5712 peer->gtsm_hops = 0;
e5cc509c
DS
5713 if (peer->sort == BGP_PEER_EBGP)
5714 ret = peer_ebgp_multihop_unset (peer);
5715 else
5716 {
5717 if (peer->fd >= 0)
5718 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 5719
e5cc509c
DS
5720 if ((peer->status < Established) && peer->doppelganger &&
5721 (peer->doppelganger->fd >= 0))
5722 sockopt_minttl (peer->su.sa.sa_family,
5723 peer->doppelganger->fd, 0);
5724 }
fa411a21
NH
5725 }
5726 }
5727
88177fe3 5728 return ret;
fa411a21 5729}
6b0655a2 5730
1ff9a340
DS
5731/*
5732 * If peer clear is invoked in a loop for all peers on the BGP instance,
5733 * it may end up freeing the doppelganger, and if this was the next node
5734 * to the current node, we would end up accessing the freed next node.
5735 * Pass along additional parameter which can be updated if next node
5736 * is freed; only required when walking the peer list on BGP instance.
5737 */
718e3744 5738int
1ff9a340 5739peer_clear (struct peer *peer, struct listnode **nnode)
718e3744 5740{
5741 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5742 {
0a486e5f 5743 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5744 {
5745 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
5746 if (peer->t_pmax_restart)
5747 {
5748 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 5749 if (bgp_debug_neighbor_events(peer))
0a486e5f 5750 zlog_debug ("%s Maximum-prefix restart timer canceled",
5751 peer->host);
5752 }
5753 BGP_EVENT_ADD (peer, BGP_Start);
5754 return 0;
5755 }
5756
718e3744 5757 peer->v_start = BGP_INIT_START_TIMER;
6aa136f1 5758 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 5759 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5760 BGP_NOTIFY_CEASE_ADMIN_RESET);
5761 else
1ff9a340 5762 bgp_session_reset_safe(peer, nnode);
718e3744 5763 }
5764 return 0;
5765}
5766
5767int
5768peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
5769 enum bgp_clear_type stype)
5770{
6a646146
DS
5771 struct peer_af *paf;
5772
718e3744 5773 if (peer->status != Established)
5774 return 0;
5775
5776 if (! peer->afc[afi][safi])
5777 return BGP_ERR_AF_UNCONFIGURED;
5778
fee0f4c6 5779 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
5780 {
5781 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
5782 return 0;
5783 bgp_check_local_routes_rsclient (peer, afi, safi);
5784 bgp_soft_reconfig_rsclient (peer, afi, safi);
5785 }
5786
718e3744 5787 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
6a646146
DS
5788 {
5789 /* Clear the "neighbor x.x.x.x default-originate" flag */
5790 paf = peer_af_find (peer, afi, safi);
5791 if (paf && paf->subgroup &&
5792 CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
5793 UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
5794
5795 bgp_announce_route (peer, afi, safi);
5796 }
718e3744 5797
5798 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
5799 {
5800 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
5801 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
5802 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
5803 {
5804 struct bgp_filter *filter = &peer->filter[afi][safi];
5805 u_char prefix_type;
5806
5807 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
5808 prefix_type = ORF_TYPE_PREFIX;
5809 else
5810 prefix_type = ORF_TYPE_PREFIX_OLD;
5811
5812 if (filter->plist[FILTER_IN].plist)
5813 {
5814 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
5815 bgp_route_refresh_send (peer, afi, safi,
5816 prefix_type, REFRESH_DEFER, 1);
5817 bgp_route_refresh_send (peer, afi, safi, prefix_type,
5818 REFRESH_IMMEDIATE, 0);
5819 }
5820 else
5821 {
5822 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
5823 bgp_route_refresh_send (peer, afi, safi,
5824 prefix_type, REFRESH_IMMEDIATE, 1);
5825 else
5826 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
5827 }
5828 return 0;
5829 }
5830 }
5831
5832 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
5833 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
5834 {
5835 /* If neighbor has soft reconfiguration inbound flag.
5836 Use Adj-RIB-In database. */
5837 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5838 bgp_soft_reconfig_in (peer, afi, safi);
5839 else
5840 {
5841 /* If neighbor has route refresh capability, send route refresh
5842 message to the peer. */
5843 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
5844 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
5845 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
5846 else
5847 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
5848 }
5849 }
5850 return 0;
5851}
6b0655a2 5852
fd79ac91 5853/* Display peer uptime.*/
5854/* XXX: why does this function return char * when it takes buffer? */
718e3744 5855char *
5856peer_uptime (time_t uptime2, char *buf, size_t len)
5857{
5858 time_t uptime1;
5859 struct tm *tm;
5860
5861 /* Check buffer length. */
5862 if (len < BGP_UPTIME_LEN)
5863 {
0cd1c32d 5864 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
fd79ac91 5865 /* XXX: should return status instead of buf... */
5866 snprintf (buf, len, "<error> ");
5867 return buf;
718e3744 5868 }
5869
5870 /* If there is no connection has been done before print `never'. */
5871 if (uptime2 == 0)
5872 {
f1aa5d8a 5873 snprintf (buf, len, "never");
718e3744 5874 return buf;
5875 }
5876
5877 /* Get current time. */
65957886 5878 uptime1 = bgp_clock ();
718e3744 5879 uptime1 -= uptime2;
5880 tm = gmtime (&uptime1);
5881
5882 /* Making formatted timer strings. */
5883#define ONE_DAY_SECOND 60*60*24
5884#define ONE_WEEK_SECOND 60*60*24*7
5885
5886 if (uptime1 < ONE_DAY_SECOND)
5887 snprintf (buf, len, "%02d:%02d:%02d",
5888 tm->tm_hour, tm->tm_min, tm->tm_sec);
5889 else if (uptime1 < ONE_WEEK_SECOND)
5890 snprintf (buf, len, "%dd%02dh%02dm",
5891 tm->tm_yday, tm->tm_hour, tm->tm_min);
5892 else
5893 snprintf (buf, len, "%02dw%dd%02dh",
5894 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
5895 return buf;
5896}
6b0655a2 5897
94f2b392 5898static void
718e3744 5899bgp_config_write_filter (struct vty *vty, struct peer *peer,
5900 afi_t afi, safi_t safi)
5901{
5902 struct bgp_filter *filter;
5903 struct bgp_filter *gfilter = NULL;
5904 char *addr;
5905 int in = FILTER_IN;
5906 int out = FILTER_OUT;
5907
5908 addr = peer->host;
5909 filter = &peer->filter[afi][safi];
5910 if (peer->af_group[afi][safi])
5911 gfilter = &peer->group->conf->filter[afi][safi];
5912
5913 /* distribute-list. */
5914 if (filter->dlist[in].name)
5915 if (! gfilter || ! gfilter->dlist[in].name
5916 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
5917 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
5918 filter->dlist[in].name, VTY_NEWLINE);
5919 if (filter->dlist[out].name && ! gfilter)
5920 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
5921 filter->dlist[out].name, VTY_NEWLINE);
5922
5923 /* prefix-list. */
5924 if (filter->plist[in].name)
5925 if (! gfilter || ! gfilter->plist[in].name
5926 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
5927 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
5928 filter->plist[in].name, VTY_NEWLINE);
5929 if (filter->plist[out].name && ! gfilter)
5930 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
5931 filter->plist[out].name, VTY_NEWLINE);
5932
5933 /* route-map. */
fee0f4c6 5934 if (filter->map[RMAP_IN].name)
5935 if (! gfilter || ! gfilter->map[RMAP_IN].name
5936 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
718e3744 5937 vty_out (vty, " neighbor %s route-map %s in%s", addr,
fee0f4c6 5938 filter->map[RMAP_IN].name, VTY_NEWLINE);
5939 if (filter->map[RMAP_OUT].name && ! gfilter)
718e3744 5940 vty_out (vty, " neighbor %s route-map %s out%s", addr,
fee0f4c6 5941 filter->map[RMAP_OUT].name, VTY_NEWLINE);
5942 if (filter->map[RMAP_IMPORT].name && ! gfilter)
5943 vty_out (vty, " neighbor %s route-map %s import%s", addr,
5944 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
5945 if (filter->map[RMAP_EXPORT].name)
5946 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
5947 || strcmp (filter->map[RMAP_EXPORT].name,
5948 gfilter->map[RMAP_EXPORT].name) != 0)
5949 vty_out (vty, " neighbor %s route-map %s export%s", addr,
5950 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
718e3744 5951
5952 /* unsuppress-map */
5953 if (filter->usmap.name && ! gfilter)
5954 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
5955 filter->usmap.name, VTY_NEWLINE);
5956
5957 /* filter-list. */
5958 if (filter->aslist[in].name)
5959 if (! gfilter || ! gfilter->aslist[in].name
5960 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
5961 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
5962 filter->aslist[in].name, VTY_NEWLINE);
5963 if (filter->aslist[out].name && ! gfilter)
5964 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
5965 filter->aslist[out].name, VTY_NEWLINE);
5966}
5967
5968/* BGP peer configuration display function. */
94f2b392 5969static void
718e3744 5970bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
5971 struct peer *peer, afi_t afi, safi_t safi)
5972{
718e3744 5973 struct peer *g_peer = NULL;
5974 char buf[SU_ADDRSTRLEN];
5975 char *addr;
5976
f14e6fdb
DS
5977 /* Skip dynamic neighbors. */
5978 if (peer_dynamic_neighbor (peer))
5979 return;
5980
a80beece
DS
5981 if (peer->conf_if)
5982 addr = peer->conf_if;
5983 else
5984 addr = peer->host;
5985
718e3744 5986 if (peer_group_active (peer))
5987 g_peer = peer->group->conf;
5988
5989 /************************************
5990 ****** Global to the neighbor ******
5991 ************************************/
5992 if (afi == AFI_IP && safi == SAFI_UNICAST)
5993 {
a80beece 5994 if (peer->conf_if)
8ffedcea
DS
5995 {
5996 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
5997 vty_out (vty, " neighbor %s interface v6only %s", addr, VTY_NEWLINE);
5998 else
5999 vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE);
6000 }
a80beece 6001
718e3744 6002 /* remote-as. */
6003 if (! peer_group_active (peer))
6004 {
6005 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
6006 vty_out (vty, " neighbor %s peer-group%s", addr,
6007 VTY_NEWLINE);
0299c004
DS
6008 if (peer->as_type == AS_SPECIFIED)
6009 {
6010 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6011 VTY_NEWLINE);
6012 }
6013 else if (peer->as_type == AS_INTERNAL)
6014 {
6015 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6016 }
6017 else if (peer->as_type == AS_EXTERNAL)
6018 {
6019 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6020 }
718e3744 6021 }
6022 else
6023 {
6024 if (! g_peer->as)
0299c004 6025 {
84f04a6d
DS
6026 if (peer->as_type == AS_SPECIFIED)
6027 {
6028 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6029 VTY_NEWLINE);
6030 }
6031 else if (peer->as_type == AS_INTERNAL)
6032 {
6033 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6034 }
6035 else if (peer->as_type == AS_EXTERNAL)
6036 {
6037 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6038 }
0299c004 6039 }
718e3744 6040 if (peer->af_group[AFI_IP][SAFI_UNICAST])
6041 vty_out (vty, " neighbor %s peer-group %s%s", addr,
6042 peer->group->name, VTY_NEWLINE);
6043 }
6044
6045 /* local-as. */
6046 if (peer->change_local_as)
6047 if (! peer_group_active (peer))
9d3f9705 6048 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
718e3744 6049 peer->change_local_as,
6050 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
9d3f9705
AC
6051 " no-prepend" : "",
6052 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
6053 " replace-as" : "", VTY_NEWLINE);
718e3744 6054
6055 /* Description. */
6056 if (peer->desc)
6057 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
6058 VTY_NEWLINE);
6059
6060 /* Shutdown. */
6061 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
6062 if (! peer_group_active (peer) ||
6063 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
6064 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
6065
d5a5c8f0 6066 /* bfd. */
7f342629
DS
6067 if (peer->bfd_info)
6068 if (! peer_group_active (peer) || ! g_peer->bfd_info)
c43ed2e4
DS
6069 {
6070 bgp_bfd_peer_config_write(vty, peer, addr);
6071 }
d5a5c8f0 6072
0df7c91f
PJ
6073 /* Password. */
6074 if (peer->password)
6075 if (!peer_group_active (peer)
6076 || ! g_peer->password
6077 || strcmp (peer->password, g_peer->password) != 0)
6078 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
6079 VTY_NEWLINE);
6080
3f9c7369
DS
6081 /* neighbor solo */
6082 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
6083 if (!peer_group_active (peer))
6084 vty_out (vty, " neighbor %s solo%s", addr, VTY_NEWLINE);
6085
718e3744 6086 /* BGP port. */
6087 if (peer->port != BGP_PORT_DEFAULT)
0df7c91f 6088 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
718e3744 6089 VTY_NEWLINE);
6090
6091 /* Local interface name. */
6092 if (peer->ifname)
6093 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
6094 VTY_NEWLINE);
6095
6096 /* Passive. */
6097 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
6098 if (! peer_group_active (peer) ||
6099 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
6100 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
6101
6102 /* EBGP multihop. */
6d85b15b 6103 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
fa411a21 6104 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
718e3744 6105 if (! peer_group_active (peer) ||
6106 g_peer->ttl != peer->ttl)
6107 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
6108 VTY_NEWLINE);
6109
fa411a21 6110 /* ttl-security hops */
5d804b43 6111 if (peer->gtsm_hops != 0)
fa411a21 6112 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
89b6d1f8 6113 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
fa411a21
NH
6114 peer->gtsm_hops, VTY_NEWLINE);
6115
6ffd2079 6116 /* disable-connected-check. */
6117 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
718e3744 6118 if (! peer_group_active (peer) ||
6ffd2079 6119 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6120 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
718e3744 6121
6122 /* Update-source. */
6123 if (peer->update_if)
6124 if (! peer_group_active (peer) || ! g_peer->update_if
6125 || strcmp (g_peer->update_if, peer->update_if) != 0)
6126 vty_out (vty, " neighbor %s update-source %s%s", addr,
6127 peer->update_if, VTY_NEWLINE);
6128 if (peer->update_source)
6129 if (! peer_group_active (peer) || ! g_peer->update_source
6130 || sockunion_cmp (g_peer->update_source,
6131 peer->update_source) != 0)
6132 vty_out (vty, " neighbor %s update-source %s%s", addr,
6133 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
6134 VTY_NEWLINE);
6135
718e3744 6136 /* advertisement-interval */
966f821c
DS
6137 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
6138 ! peer_group_active (peer))
718e3744 6139 vty_out (vty, " neighbor %s advertisement-interval %d%s",
6140 addr, peer->v_routeadv, VTY_NEWLINE);
6141
6142 /* timers. */
6143 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
6144 && ! peer_group_active (peer))
6145 vty_out (vty, " neighbor %s timers %d %d%s", addr,
6146 peer->keepalive, peer->holdtime, VTY_NEWLINE);
6147
966f821c
DS
6148 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
6149 ! peer_group_active (peer))
718e3744 6150 vty_out (vty, " neighbor %s timers connect %d%s", addr,
6151 peer->connect, VTY_NEWLINE);
6152
6153 /* Default weight. */
6154 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
6155 if (! peer_group_active (peer) ||
6156 g_peer->weight != peer->weight)
6157 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
6158 VTY_NEWLINE);
6159
718e3744 6160 /* Dynamic capability. */
6161 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6162 if (! peer_group_active (peer) ||
6163 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6164 vty_out (vty, " neighbor %s capability dynamic%s", addr,
6165 VTY_NEWLINE);
6166
8a92a8a0
DS
6167 /* Extended next-hop capability. */
6168 if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6169 if (! peer_group_active (peer) ||
6170 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6171 vty_out (vty, " neighbor %s capability extended-nexthop%s", addr,
6172 VTY_NEWLINE);
6173
718e3744 6174 /* dont capability negotiation. */
6175 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
6176 if (! peer_group_active (peer) ||
6177 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
6178 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
6179 VTY_NEWLINE);
6180
6181 /* override capability negotiation. */
6182 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6183 if (! peer_group_active (peer) ||
6184 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6185 vty_out (vty, " neighbor %s override-capability%s", addr,
6186 VTY_NEWLINE);
6187
6188 /* strict capability negotiation. */
6189 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
6190 if (! peer_group_active (peer) ||
6191 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
6192 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
6193 VTY_NEWLINE);
6194
15c71348 6195 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
718e3744 6196 {
6197 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6198 {
6199 if (peer->afc[AFI_IP][SAFI_UNICAST])
6200 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
6201 }
6202 else
6203 {
6204 if (! peer->afc[AFI_IP][SAFI_UNICAST])
6205 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
6206 }
6207 }
6208 }
6209
6210
6211 /************************************
6212 ****** Per AF to the neighbor ******
6213 ************************************/
6214
6215 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
6216 {
6217 if (peer->af_group[afi][safi])
6218 vty_out (vty, " neighbor %s peer-group %s%s", addr,
6219 peer->group->name, VTY_NEWLINE);
6220 else
6221 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
6222 }
6223
6224 /* ORF capability. */
6225 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
6226 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
6227 if (! peer->af_group[afi][safi])
6228 {
6229 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
6230
6231 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
6232 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
6233 vty_out (vty, " both");
6234 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
6235 vty_out (vty, " send");
6236 else
6237 vty_out (vty, " receive");
6238 vty_out (vty, "%s", VTY_NEWLINE);
6239 }
6240
6241 /* Route reflector client. */
6242 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
6243 && ! peer->af_group[afi][safi])
6244 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
6245 VTY_NEWLINE);
6246
6247 /* Nexthop self. */
a538debe 6248 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)
718e3744 6249 && ! peer->af_group[afi][safi])
a538debe
DS
6250 vty_out (vty, " neighbor %s next-hop-self force%s",
6251 addr, VTY_NEWLINE);
6252 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
6253 && ! peer->af_group[afi][safi])
6254 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
718e3744 6255
5000f21c
DS
6256 /* remove-private-AS */
6257 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi])
6258 {
6259 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) &&
6260 peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
6261 vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE);
6262
6263 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
6264 vty_out (vty, " neighbor %s remove-private-AS replace-AS%s", addr, VTY_NEWLINE);
6265
6266 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
6267 vty_out (vty, " neighbor %s remove-private-AS all%s", addr, VTY_NEWLINE);
6268
6269 else
6270 vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE);
6271 }
718e3744 6272
c7122e14
DS
6273 /* as-override */
6274 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) &&
6275 !peer->af_group[afi][safi])
6276 vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE);
6277
718e3744 6278 /* send-community print. */
6279 if (! peer->af_group[afi][safi])
6280 {
6281 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6282 {
6283 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6284 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6285 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
6286 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6287 vty_out (vty, " neighbor %s send-community extended%s",
6288 addr, VTY_NEWLINE);
6289 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
6290 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
6291 }
6292 else
6293 {
6294 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6295 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6296 vty_out (vty, " no neighbor %s send-community both%s",
6297 addr, VTY_NEWLINE);
6298 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6299 vty_out (vty, " no neighbor %s send-community extended%s",
6300 addr, VTY_NEWLINE);
6301 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
6302 vty_out (vty, " no neighbor %s send-community%s",
6303 addr, VTY_NEWLINE);
6304 }
6305 }
6306
6307 /* Default information */
6308 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
6309 && ! peer->af_group[afi][safi])
6310 {
6311 vty_out (vty, " neighbor %s default-originate", addr);
6312 if (peer->default_rmap[afi][safi].name)
6313 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
6314 vty_out (vty, "%s", VTY_NEWLINE);
6315 }
6316
6317 /* Soft reconfiguration inbound. */
6318 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6319 if (! peer->af_group[afi][safi] ||
6320 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6321 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
6322 VTY_NEWLINE);
6323
6324 /* maximum-prefix. */
6325 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
6326 if (! peer->af_group[afi][safi]
6327 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
e0701b79 6328 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
718e3744 6329 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
6330 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
e0701b79 6331 {
0a486e5f 6332 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
6333 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6334 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
6335 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
6336 vty_out (vty, " warning-only");
6337 if (peer->pmax_restart[afi][safi])
6338 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
6339 vty_out (vty, "%s", VTY_NEWLINE);
e0701b79 6340 }
718e3744 6341
6342 /* Route server client. */
6343 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
6344 && ! peer->af_group[afi][safi])
6345 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
6346
3cf1288b
DH
6347 /* Nexthop-local unchanged. */
6348 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
6349 && ! peer->af_group[afi][safi])
6350 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
6351
718e3744 6352 /* Allow AS in. */
6353 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
6354 if (! peer_group_active (peer)
6355 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
6356 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
6357 {
6358 if (peer->allowas_in[afi][safi] == 3)
6359 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
6360 else
6361 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
6362 peer->allowas_in[afi][safi], VTY_NEWLINE);
6363 }
6364
6365 /* Filter. */
6366 bgp_config_write_filter (vty, peer, afi, safi);
6367
6368 /* atribute-unchanged. */
6369 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
6370 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
6371 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
6372 && ! peer->af_group[afi][safi])
6373 {
6374 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
6375 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
6376 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
6377 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
6378 else
6379 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
6380 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
6381 " as-path" : "",
6382 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
6383 " next-hop" : "",
6384 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
6385 " med" : "", VTY_NEWLINE);
6386 }
6387}
6388
6389/* Display "address-family" configuration header. */
6390void
6391bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
6392 int *write)
6393{
6394 if (*write)
6395 return;
6396
6397 if (afi == AFI_IP && safi == SAFI_UNICAST)
6398 return;
6399
6400 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
6401
6402 if (afi == AFI_IP)
6403 {
6404 if (safi == SAFI_MULTICAST)
6405 vty_out (vty, "ipv4 multicast");
6406 else if (safi == SAFI_MPLS_VPN)
6407 vty_out (vty, "vpnv4 unicast");
6408 }
6409 else if (afi == AFI_IP6)
37a217a5
PJ
6410 {
6411 vty_out (vty, "ipv6");
6412
6413 if (safi == SAFI_MULTICAST)
6414 vty_out (vty, " multicast");
6415 }
718e3744 6416
6417 vty_out (vty, "%s", VTY_NEWLINE);
6418
6419 *write = 1;
6420}
6421
6422/* Address family based peer configuration display. */
94f2b392 6423static int
718e3744 6424bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
6425 safi_t safi)
6426{
6427 int write = 0;
6428 struct peer *peer;
6429 struct peer_group *group;
1eb8ef25 6430 struct listnode *node, *nnode;
718e3744 6431
6432 bgp_config_write_network (vty, bgp, afi, safi, &write);
6433
6434 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
6435
1eb8ef25 6436 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 6437 {
6438 if (group->conf->afc[afi][safi])
6439 {
6440 bgp_config_write_family_header (vty, afi, safi, &write);
6441 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
6442 }
6443 }
1eb8ef25 6444 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 6445 {
f14e6fdb
DS
6446 /* Skip dynamic neighbors. */
6447 if (peer_dynamic_neighbor (peer))
6448 continue;
6449
718e3744 6450 if (peer->afc[afi][safi])
6451 {
1ff9a340 6452 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
718e3744 6453 {
6454 bgp_config_write_family_header (vty, afi, safi, &write);
6455 bgp_config_write_peer (vty, bgp, peer, afi, safi);
6456 }
6457 }
6458 }
165b5fff
JB
6459
6460 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
73ac8160 6461 bgp_config_write_table_map (vty, bgp, afi, safi, &write);
165b5fff 6462
718e3744 6463 if (write)
6464 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
6465
6466 return write;
6467}
6468
6469int
6470bgp_config_write (struct vty *vty)
6471{
6472 int write = 0;
6473 struct bgp *bgp;
6474 struct peer_group *group;
6475 struct peer *peer;
1eb8ef25 6476 struct listnode *node, *nnode;
6477 struct listnode *mnode, *mnnode;
718e3744 6478
6479 /* BGP Multiple instance. */
6480 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
6481 {
6482 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
6483 write++;
6484 }
6485
6486 /* BGP Config type. */
6487 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6488 {
6489 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
6490 write++;
6491 }
6492
6493 /* BGP configuration. */
1eb8ef25 6494 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 6495 {
6496 if (write)
6497 vty_out (vty, "!%s", VTY_NEWLINE);
6498
6499 /* Router bgp ASN */
aea339f7 6500 vty_out (vty, "router bgp %u", bgp->as);
718e3744 6501
6502 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
6503 {
6504 if (bgp->name)
6505 vty_out (vty, " view %s", bgp->name);
6506 }
6507 vty_out (vty, "%s", VTY_NEWLINE);
6508
6509 /* No Synchronization */
6510 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6511 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
6512
6513 /* BGP fast-external-failover. */
6514 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
6515 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
6516
6517 /* BGP router ID. */
6518 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
6519 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
6520 VTY_NEWLINE);
6521
848973c7 6522 /* BGP log-neighbor-changes. */
6523 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
6524 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
6525
718e3744 6526 /* BGP configuration. */
6527 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
6528 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
6529
6530 /* BGP default ipv4-unicast. */
6531 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6532 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
6533
6534 /* BGP default local-preference. */
6535 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
6536 vty_out (vty, " bgp default local-preference %d%s",
6537 bgp->default_local_pref, VTY_NEWLINE);
6538
3f9c7369
DS
6539 /* BGP default subgroup-pkt-queue-max. */
6540 if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
6541 vty_out (vty, " bgp default subgroup-pkt-queue-max %d%s",
6542 bgp->default_subgroup_pkt_queue_max, VTY_NEWLINE);
6543
718e3744 6544 /* BGP client-to-client reflection. */
6545 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
6546 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
6547
6548 /* BGP cluster ID. */
6549 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
6550 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
6551 VTY_NEWLINE);
6552
907f92c8
DS
6553 /* Disable ebgp connected nexthop check */
6554 if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
6555 vty_out (vty, " bgp disable-ebgp-connected-route-check%s", VTY_NEWLINE);
6556
e0701b79 6557 /* Confederation identifier*/
718e3744 6558 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
e0701b79 6559 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
6560 VTY_NEWLINE);
6561
6562 /* Confederation peer */
6563 if (bgp->confed_peers_cnt > 0)
718e3744 6564 {
e0701b79 6565 int i;
718e3744 6566
e0701b79 6567 vty_out (vty, " bgp confederation peers");
718e3744 6568
e0701b79 6569 for (i = 0; i < bgp->confed_peers_cnt; i++)
aea339f7 6570 vty_out(vty, " %u", bgp->confed_peers[i]);
718e3744 6571
e0701b79 6572 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6573 }
6574
6575 /* BGP enforce-first-as. */
6576 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
6577 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
6578
6579 /* BGP deterministic-med. */
6580 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
6581 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
538621f2 6582
f188f2c4
DS
6583 /* BGP update-delay. */
6584 bgp_config_write_update_delay (vty, bgp);
6585
abc920f8
DS
6586 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
6587 {
6588 vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
6589 if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
6590 vty_out (vty, " %d", bgp->maxmed_onstartup_value);
6591 vty_out (vty, "%s", VTY_NEWLINE);
6592 }
6593 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
6594 {
6595 vty_out (vty, " bgp max-med administrative");
6596 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
6597 vty_out (vty, " %d", bgp->maxmed_admin_value);
6598 vty_out (vty, "%s", VTY_NEWLINE);
6599 }
6600
cb1faec9
DS
6601 /* write quanta */
6602 bgp_config_write_wpkt_quanta (vty, bgp);
6603
3f9c7369
DS
6604 /* coalesce time */
6605 bgp_config_write_coalesce_time(vty, bgp);
6606
538621f2 6607 /* BGP graceful-restart. */
93406d87 6608 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
6609 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
6610 bgp->stalepath_time, VTY_NEWLINE);
538621f2 6611 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
6612 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
6613
718e3744 6614 /* BGP bestpath method. */
6615 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
6616 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
6811845b 6617 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
6618 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
16fc1eec 6619
2fdd455c 6620 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
16fc1eec
DS
6621 if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_NO_AS_SET)) {
6622 vty_out (vty, " bgp bestpath as-path multipath-relax no-as-set%s", VTY_NEWLINE);
6623 } else {
6624 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
6625 }
2fdd455c 6626 }
16fc1eec 6627
8bd9d948
DS
6628 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6629 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
6630 VTY_NEWLINE);
6631 }
718e3744 6632 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
6633 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
6634 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
6635 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
6636 {
6637 vty_out (vty, " bgp bestpath med");
6638 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
6639 vty_out (vty, " confed");
6640 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
6641 vty_out (vty, " missing-as-worst");
6642 vty_out (vty, "%s", VTY_NEWLINE);
6643 }
6644
6645 /* BGP network import check. */
078430f6
DS
6646 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK_EXACT_MATCH))
6647 vty_out (vty, " bgp network import-check exact%s", VTY_NEWLINE);
6648 else if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
718e3744 6649 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
6650
718e3744 6651 /* BGP flag dampening. */
6652 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
6653 BGP_CONFIG_DAMPENING))
6654 bgp_config_write_damp (vty);
6655
6656 /* BGP static route configuration. */
6657 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
6658
6659 /* BGP redistribute configuration. */
6660 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
6661
6662 /* BGP timers configuration. */
6663 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
6664 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
6665 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
6666 bgp->default_holdtime, VTY_NEWLINE);
6667
518f0eb1
DS
6668 if (bgp->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
6669 vty_out (vty, " bgp route-map delay-timer %d%s", bgp->rmap_update_timer,
6670 VTY_NEWLINE);
6671
718e3744 6672 /* peer-group */
1eb8ef25 6673 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 6674 {
6675 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
6676 }
6677
6678 /* Normal neighbor configuration. */
1eb8ef25 6679 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 6680 {
1ff9a340 6681 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
718e3744 6682 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
6683 }
6684
165b5fff
JB
6685 /* maximum-paths */
6686 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
73ac8160 6687 bgp_config_write_table_map (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
165b5fff 6688
718e3744 6689 /* Distance configuration. */
6690 bgp_config_write_distance (vty, bgp);
6691
f14e6fdb
DS
6692 /* listen range and limit for dynamic BGP neighbors */
6693 bgp_config_write_listen (vty, bgp);
6694
718e3744 6695 /* No auto-summary */
6696 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6697 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
6698
6699 /* IPv4 multicast configuration. */
6700 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
6701
6702 /* IPv4 VPN configuration. */
6703 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
6704
6705 /* IPv6 unicast configuration. */
6706 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
6707
37a217a5
PJ
6708 /* IPv6 multicast configuration. */
6709 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
6710
718e3744 6711 write++;
6712 }
6713 return write;
6714}
6715
6716void
94f2b392 6717bgp_master_init (void)
718e3744 6718{
6719 memset (&bgp_master, 0, sizeof (struct bgp_master));
6720
6721 bm = &bgp_master;
6722 bm->bgp = list_new ();
0df7c91f 6723 bm->listen_sockets = list_new ();
718e3744 6724 bm->port = BGP_PORT_DEFAULT;
6725 bm->master = thread_master_create ();
65957886 6726 bm->start_time = bgp_clock ();
718e3744 6727}
200df115 6728
6b0655a2 6729
718e3744 6730void
94f2b392 6731bgp_init (void)
718e3744 6732{
fc9a856f
DS
6733
6734 /* allocates some vital data structures used by peer commands in vty_init */
6735 bgp_scan_init ();
718e3744 6736
718e3744 6737 /* Init zebra. */
6738 bgp_zebra_init ();
6739
fc9a856f
DS
6740 /* BGP VTY commands installation. */
6741 bgp_vty_init ();
6742
718e3744 6743 /* BGP inits. */
6744 bgp_attr_init ();
6745 bgp_debug_init ();
6746 bgp_dump_init ();
6747 bgp_route_init ();
6748 bgp_route_map_init ();
10f9bf3f 6749 bgp_address_init ();
fc9a856f 6750 bgp_scan_vty_init();
718e3744 6751 bgp_mplsvpn_init ();
6752
6753 /* Access list initialize. */
6754 access_list_init ();
6755 access_list_add_hook (peer_distribute_update);
6756 access_list_delete_hook (peer_distribute_update);
6757
6758 /* Filter list initialize. */
6759 bgp_filter_init ();
518f0eb1
DS
6760 as_list_add_hook (peer_aslist_add);
6761 as_list_delete_hook (peer_aslist_del);
718e3744 6762
6763 /* Prefix list initialize.*/
6764 prefix_list_init ();
6765 prefix_list_add_hook (peer_prefix_list_update);
6766 prefix_list_delete_hook (peer_prefix_list_update);
6767
6768 /* Community list initialize. */
6769 bgp_clist = community_list_init ();
6770
6771#ifdef HAVE_SNMP
6772 bgp_snmp_init ();
6773#endif /* HAVE_SNMP */
c43ed2e4
DS
6774
6775 /* BFD init */
6776 bgp_bfd_init();
718e3744 6777}
545acafb 6778
6779void
66e5cd87 6780bgp_terminate (void)
545acafb 6781{
545acafb 6782 struct bgp *bgp;
6783 struct peer *peer;
1eb8ef25 6784 struct listnode *node, *nnode;
6785 struct listnode *mnode, *mnnode;
545acafb 6786
1ff9a340
DS
6787 /* Close the listener sockets first as this prevents peers from attempting
6788 * to reconnect on receiving the peer unconfig message. In the presence
6789 * of a large number of peers this will ensure that no peer is left with
6790 * a dangling connection
6791 */
6792 /* reverse bgp_master_init */
6793 bgp_close();
6794 if (bm->listen_sockets)
6795 list_free(bm->listen_sockets);
6796 bm->listen_sockets = NULL;
6797
1eb8ef25 6798 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
6799 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
1ff9a340
DS
6800 if (peer->status == Established ||
6801 peer->status == OpenSent ||
6802 peer->status == OpenConfirm)
545acafb 6803 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
6804 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
1ff9a340 6805
545acafb 6806 bgp_cleanup_routes ();
acde4b86 6807
e210cf9f 6808 if (bm->process_main_queue)
acde4b86
SH
6809 {
6810 work_queue_free (bm->process_main_queue);
6811 bm->process_main_queue = NULL;
6812 }
e210cf9f 6813 if (bm->process_rsclient_queue)
acde4b86
SH
6814 {
6815 work_queue_free (bm->process_rsclient_queue);
6816 bm->process_rsclient_queue = NULL;
6817 }
545acafb 6818}