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