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