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