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