]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
bgpd-nht-import-check-fix.patch
[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
518f0eb1
DS
2615 bgp->t_rmap_update = NULL;
2616 bgp->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
2617
ad12dde6 2618 /* Create BGP server socket, if first instance. */
cccbc015
PJ
2619 if (list_isempty(bm->bgp)
2620 && !bgp_option_check (BGP_OPT_NO_LISTEN))
ad12dde6
PJ
2621 {
2622 if (bgp_socket (bm->port, bm->address) < 0)
2623 return BGP_ERR_INVALID_VALUE;
2624 }
2625
718e3744 2626 listnode_add (bm->bgp, bgp);
718e3744 2627
2628 return 0;
2629}
2630
2631/* Delete BGP instance. */
2632int
2633bgp_delete (struct bgp *bgp)
2634{
2635 struct peer *peer;
b6b7cff2 2636 struct peer_group *group;
1eb8ef25 2637 struct listnode *node;
718e3744 2638 struct listnode *next;
2639 afi_t afi;
718e3744 2640 int i;
2641
d4a7a753
DS
2642 THREAD_OFF (bgp->t_startup);
2643
cd92e548
DS
2644 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2645 {
2646 if (peer->status == Established ||
2647 peer->status == OpenSent ||
2648 peer->status == OpenConfirm)
2649 {
2650 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2651 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2652 }
2653 }
2654
518f0eb1
DS
2655 if (bgp->t_rmap_update)
2656 BGP_TIMER_OFF(bgp->t_rmap_update);
2657
718e3744 2658 /* Delete static route. */
2659 bgp_static_delete (bgp);
2660
2661 /* Unset redistribution. */
2662 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2663 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2664 if (i != ZEBRA_ROUTE_BGP)
7c8ff89e 2665 bgp_redistribute_unset (bgp, afi, i, 0);
718e3744 2666
228da428 2667 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
6aa136f1
VS
2668 {
2669 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2670 {
2671 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2672 {
2673 /* Send notify to remote peer. */
2674 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2675 }
2676 }
2677 peer_group_delete (group);
2678 }
228da428 2679
1ff9a340
DS
2680 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2681 {
2682 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2683 {
2684 /* Send notify to remote peer. */
2685 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2686 }
2687
2688 peer_delete (peer);
2689 }
2690
228da428 2691 assert (listcount (bgp->rsclient) == 0);
0088b5dc
SH
2692
2693 if (bgp->peer_self) {
2694 peer_delete(bgp->peer_self);
2695 bgp->peer_self = NULL;
2696 }
fd35b948
PJ
2697
2698 /* Remove visibility via the master list - there may however still be
2699 * routes to be processed still referencing the struct bgp.
2700 */
2701 listnode_delete (bm->bgp, bgp);
d023aec4
SH
2702 if (list_isempty(bm->bgp))
2703 bgp_close ();
2704
0088b5dc 2705 bgp_unlock(bgp); /* initial reference */
fd35b948 2706
0088b5dc
SH
2707 return 0;
2708}
2709
2710static void bgp_free (struct bgp *);
2711
2712void
2713bgp_lock (struct bgp *bgp)
2714{
2715 ++bgp->lock;
2716}
2717
2718void
2719bgp_unlock(struct bgp *bgp)
2720{
228da428 2721 assert(bgp->lock > 0);
0088b5dc
SH
2722 if (--bgp->lock == 0)
2723 bgp_free (bgp);
2724}
2725
2726static void
2727bgp_free (struct bgp *bgp)
2728{
2729 afi_t afi;
2730 safi_t safi;
2731
2732 list_delete (bgp->group);
2733 list_delete (bgp->peer);
fee0f4c6 2734 list_delete (bgp->rsclient);
2735
718e3744 2736 if (bgp->name)
2737 free (bgp->name);
2738
2739 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2740 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2741 {
2742 if (bgp->route[afi][safi])
228da428 2743 bgp_table_finish (&bgp->route[afi][safi]);
718e3744 2744 if (bgp->aggregate[afi][safi])
228da428 2745 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
718e3744 2746 if (bgp->rib[afi][safi])
228da428 2747 bgp_table_finish (&bgp->rib[afi][safi]);
718e3744 2748 }
2749 XFREE (MTYPE_BGP, bgp);
718e3744 2750}
6b0655a2 2751
a80beece
DS
2752struct peer *
2753peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if)
2754{
2755 struct peer *peer;
2756 struct listnode *node, *nnode;
2757
2758 if (!conf_if)
2759 return NULL;
2760
2761 if (bgp != NULL)
2762 {
2763 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2764 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
2765 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2766 return peer;
2767 }
2768 else if (bm->bgp != NULL)
2769 {
2770 struct listnode *bgpnode, *nbgpnode;
2771
2772 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2773 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2774 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
2775 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2776 return peer;
2777 }
2778 return NULL;
2779}
2780
718e3744 2781struct peer *
2782peer_lookup (struct bgp *bgp, union sockunion *su)
2783{
2784 struct peer *peer;
1eb8ef25 2785 struct listnode *node, *nnode;
718e3744 2786
fc4dc59d 2787 if (bgp != NULL)
fc4dc59d 2788 {
2158ad23
PJ
2789 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2790 if (sockunion_same (&peer->su, su)
1ff9a340 2791 && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
2158ad23 2792 return peer;
fc4dc59d 2793 }
fc4dc59d 2794 else if (bm->bgp != NULL)
718e3744 2795 {
2158ad23
PJ
2796 struct listnode *bgpnode, *nbgpnode;
2797
2798 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2799 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2800 if (sockunion_same (&peer->su, su)
1ff9a340 2801 && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
2158ad23 2802 return peer;
fc4dc59d 2803 }
718e3744 2804 return NULL;
2805}
2806
f14e6fdb
DS
2807struct peer *
2808peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
2809 struct peer_group *group)
2810{
2811 struct peer *peer;
2812 afi_t afi;
2813 safi_t safi;
2814 as_t as;
2815
2816 /* Create peer first; we've already checked group config is valid. */
2817 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, 0, 0);
2818 if (!peer)
2819 return NULL;
2820
2821 /* Link to group */
2822 peer->group = group;
2823 peer = peer_lock (peer);
2824 listnode_add (group->peer, peer);
2825
2826 /*
2827 * Bind peer for all AFs configured for the group. We don't call
2828 * peer_group_bind as that is sub-optimal and does some stuff we don't want.
2829 */
2830 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2831 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2832 {
2833 if (!group->conf->afc[afi][safi])
2834 continue;
2835 peer->af_group[afi][safi] = 1;
2836 peer->afc[afi][safi] = 1;
2837 if (!peer_af_find(peer, afi, safi) &&
2838 peer_af_create(peer, afi, safi) == NULL)
2839 {
2840 zlog_err("couldn't create af structure for peer %s", peer->host);
2841 }
2842 peer_group2peer_config_copy (group, peer, afi, safi);
2843 }
2844
2845 /* Mark as dynamic, but also as a "config node" for other things to work. */
2846 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
2847 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
2848
2849 return peer;
2850}
2851
2852struct prefix *
2853peer_group_lookup_dynamic_neighbor_range (struct peer_group * group,
2854 struct prefix * prefix)
2855{
2856 struct listnode *node, *nnode;
2857 struct prefix *range;
2858 afi_t afi;
2859
2860 afi = family2afi(prefix->family);
2861
2862 if (group->listen_range[afi])
2863 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range))
2864 if (prefix_match(range, prefix))
2865 return range;
2866
2867 return NULL;
2868}
2869
2870struct peer_group *
2871peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix,
2872 struct prefix **listen_range)
2873{
2874 struct prefix *range = NULL;
2875 struct peer_group *group = NULL;
2876 struct listnode *node, *nnode;
2877
2878 *listen_range = NULL;
2879 if (bgp != NULL)
2880 {
2881 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
2882 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
2883 break;
2884 }
2885 else if (bm->bgp != NULL)
2886 {
2887 struct listnode *bgpnode, *nbgpnode;
2888
2889 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2890 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
2891 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
2892 break;
2893 }
2894
2895 *listen_range = range;
2896 return (group && range) ? group : NULL;
2897}
2898
2899struct peer *
2900peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
2901{
2902 struct peer_group *group;
2903 struct bgp *gbgp;
2904 struct peer *peer;
2905 struct prefix *prefix;
2906 struct prefix *listen_range;
2907 int dncount;
2908 char buf[SU_ADDRSTRLEN];
2909 char buf1[SU_ADDRSTRLEN];
2910
2911 prefix = sockunion2hostprefix(su);
2912 if (!prefix)
2913 return NULL;
2914
2915 /* See if incoming connection matches a configured listen range. */
2916 group = peer_group_lookup_dynamic_neighbor (bgp, prefix, &listen_range);
2917
2918 if (! group)
2919 return NULL;
2920
2921 gbgp = group->bgp;
2922
2923 if (! gbgp)
2924 return NULL;
2925
2926 prefix2str(prefix, buf, sizeof(buf));
2927 prefix2str(listen_range, buf1, sizeof(buf1));
2928
2929 if (bgp_debug_neighbor_events(NULL))
2930 zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s",
2931 buf, group->name, buf1);
2932
2933 /* Are we within the listen limit? */
2934 dncount = gbgp->dynamic_neighbors_count;
2935
2936 if (dncount >= gbgp->dynamic_neighbors_limit)
2937 {
2938 if (bgp_debug_neighbor_events(NULL))
2939 zlog_debug ("Dynamic Neighbor %s rejected - at limit %d",
2940 inet_sutop (su, buf), gbgp->dynamic_neighbors_limit);
2941 return NULL;
2942 }
2943
2944 /* Ensure group is not disabled. */
2945 if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN))
2946 {
2947 if (bgp_debug_neighbor_events(NULL))
2948 zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled",
2949 buf, group->name);
2950 return NULL;
2951 }
2952
2953 /* Check that at least one AF is activated for the group. */
2954 if (!peer_group_af_configured (group))
2955 {
2956 if (bgp_debug_neighbor_events(NULL))
2957 zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s",
2958 buf, group->name);
2959 return NULL;
2960 }
2961
2962 /* Create dynamic peer and bind to associated group. */
2963 peer = peer_create_bind_dynamic_neighbor (gbgp, su, group);
2964 assert (peer);
2965
2966 gbgp->dynamic_neighbors_count = ++dncount;
2967
2968 if (bgp_debug_neighbor_events(peer))
2969 zlog_debug ("%s Dynamic Neighbor added, group %s count %d",
2970 peer->host, group->name, dncount);
2971
2972 return peer;
2973}
2974
2975void peer_drop_dynamic_neighbor (struct peer *peer)
2976{
2977 int dncount = -1;
2978 if (peer->group && peer->group->bgp)
2979 {
2980 dncount = peer->group->bgp->dynamic_neighbors_count;
2981 if (dncount)
2982 peer->group->bgp->dynamic_neighbors_count = --dncount;
2983 }
2984 if (bgp_debug_neighbor_events(peer))
2985 zlog_debug ("%s dropped from group %s, count %d",
2986 peer->host, peer->group->name, dncount);
2987}
2988
2989
718e3744 2990/* If peer is configured at least one address family return 1. */
2991int
2992peer_active (struct peer *peer)
2993{
a80beece
DS
2994 if (BGP_PEER_SU_UNSPEC(peer))
2995 return 0;
718e3744 2996 if (peer->afc[AFI_IP][SAFI_UNICAST]
2997 || peer->afc[AFI_IP][SAFI_MULTICAST]
2998 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2999 || peer->afc[AFI_IP6][SAFI_UNICAST]
3000 || peer->afc[AFI_IP6][SAFI_MULTICAST])
3001 return 1;
3002 return 0;
3003}
3004
3005/* If peer is negotiated at least one address family return 1. */
3006int
3007peer_active_nego (struct peer *peer)
3008{
3009 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3010 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3011 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
3012 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
3013 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
3014 return 1;
3015 return 0;
3016}
6b0655a2 3017
718e3744 3018/* peer_flag_change_type. */
3019enum peer_change_type
3020{
3021 peer_change_none,
3022 peer_change_reset,
3023 peer_change_reset_in,
3024 peer_change_reset_out,
3025};
3026
94f2b392 3027static void
718e3744 3028peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
3029 enum peer_change_type type)
3030{
3031 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3032 return;
3033
d9d4ae51
SH
3034 if (peer->status != Established)
3035 return;
3036
718e3744 3037 if (type == peer_change_reset)
1ff9a340
DS
3038 {
3039 /* If we're resetting session, we've to delete both peer struct */
3040 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3041 && (!CHECK_FLAG(peer->doppelganger->flags,
3042 PEER_FLAG_CONFIG_NODE)))
3043 peer_delete(peer->doppelganger);
3044
3045 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3046 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3047 }
718e3744 3048 else if (type == peer_change_reset_in)
3049 {
3050 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3051 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3052 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3053 else
1ff9a340
DS
3054 {
3055 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3056 && (!CHECK_FLAG(peer->doppelganger->flags,
3057 PEER_FLAG_CONFIG_NODE)))
3058 peer_delete(peer->doppelganger);
3059
3060 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3061 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3062 }
718e3744 3063 }
3064 else if (type == peer_change_reset_out)
3f9c7369
DS
3065 {
3066 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3067 bgp_announce_route (peer, afi, safi);
3068 }
718e3744 3069}
3070
3071struct peer_flag_action
3072{
3073 /* Peer's flag. */
3074 u_int32_t flag;
3075
3076 /* This flag can be set for peer-group member. */
3077 u_char not_for_member;
3078
3079 /* Action when the flag is changed. */
3080 enum peer_change_type type;
e0701b79 3081
3082 /* Peer down cause */
3083 u_char peer_down;
718e3744 3084};
3085
03621955 3086static const struct peer_flag_action peer_flag_action_list[] =
718e3744 3087 {
3088 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
3089 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
3090 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
3091 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
3092 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
718e3744 3093 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
6ffd2079 3094 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
d5a5c8f0 3095 { PEER_FLAG_BFD, 0, peer_change_none },
718e3744 3096 { 0, 0, 0 }
3097 };
3098
03621955 3099static const struct peer_flag_action peer_af_flag_action_list[] =
718e3744 3100 {
3101 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
3102 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
3103 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
3104 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
3105 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
3106 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
3107 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
3108 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
3109 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
3110 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
5000f21c
DS
3111 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
3112 { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
718e3744 3113 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
3114 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
3115 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
fee0f4c6 3116 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
9e7a53c1 3117 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
c7122e14 3118 { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
718e3744 3119 { 0, 0, 0 }
3120 };
3121
3122/* Proper action set. */
94f2b392 3123static int
03621955 3124peer_flag_action_set (const struct peer_flag_action *action_list, int size,
718e3744 3125 struct peer_flag_action *action, u_int32_t flag)
3126{
3127 int i;
3128 int found = 0;
3129 int reset_in = 0;
3130 int reset_out = 0;
03621955 3131 const struct peer_flag_action *match = NULL;
718e3744 3132
3133 /* Check peer's frag action. */
3134 for (i = 0; i < size; i++)
3135 {
3136 match = &action_list[i];
3137
3138 if (match->flag == 0)
3139 break;
3140
3141 if (match->flag & flag)
3142 {
3143 found = 1;
3144
3145 if (match->type == peer_change_reset_in)
3146 reset_in = 1;
3147 if (match->type == peer_change_reset_out)
3148 reset_out = 1;
3149 if (match->type == peer_change_reset)
3150 {
3151 reset_in = 1;
3152 reset_out = 1;
3153 }
3154 if (match->not_for_member)
3155 action->not_for_member = 1;
3156 }
3157 }
3158
3159 /* Set peer clear type. */
3160 if (reset_in && reset_out)
3161 action->type = peer_change_reset;
3162 else if (reset_in)
3163 action->type = peer_change_reset_in;
3164 else if (reset_out)
3165 action->type = peer_change_reset_out;
3166 else
3167 action->type = peer_change_none;
3168
3169 return found;
3170}
3171
94f2b392 3172static void
718e3744 3173peer_flag_modify_action (struct peer *peer, u_int32_t flag)
3174{
3175 if (flag == PEER_FLAG_SHUTDOWN)
3176 {
3177 if (CHECK_FLAG (peer->flags, flag))
3178 {
93406d87 3179 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3180 peer_nsf_stop (peer);
3181
0a486e5f 3182 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3183 if (peer->t_pmax_restart)
3184 {
3185 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 3186 if (bgp_debug_neighbor_events(peer))
0a486e5f 3187 zlog_debug ("%s Maximum-prefix restart timer canceled",
3188 peer->host);
3189 }
3190
1ff9a340
DS
3191 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3192 peer_nsf_stop (peer);
93406d87 3193
6aa136f1 3194 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3196 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3197 else
1ff9a340 3198 bgp_session_reset(peer);
718e3744 3199 }
3200 else
3201 {
3202 peer->v_start = BGP_INIT_START_TIMER;
3203 BGP_EVENT_ADD (peer, BGP_Stop);
3204 }
3205 }
6aa136f1 3206 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3207 {
c9502438 3208 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3209 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3210 else if (flag == PEER_FLAG_PASSIVE)
3211 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
6ffd2079 3212 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
c9502438 3213 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
e0701b79 3214
c9502438 3215 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3216 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
718e3744 3217 }
3218 else
1ff9a340 3219 bgp_session_reset(peer);
718e3744 3220}
3221
3222/* Change specified peer flag. */
94f2b392 3223static int
718e3744 3224peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
3225{
3226 int found;
3227 int size;
3228 struct peer_group *group;
1eb8ef25 3229 struct listnode *node, *nnode;
718e3744 3230 struct peer_flag_action action;
3231
3232 memset (&action, 0, sizeof (struct peer_flag_action));
3233 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
3234
3235 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
3236
3237 /* No flag action is found. */
3238 if (! found)
3239 return BGP_ERR_INVALID_FLAG;
3240
3241 /* Not for peer-group member. */
3242 if (action.not_for_member && peer_group_active (peer))
3243 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3244
3245 /* When unset the peer-group member's flag we have to check
3246 peer-group configuration. */
3247 if (! set && peer_group_active (peer))
3248 if (CHECK_FLAG (peer->group->conf->flags, flag))
3249 {
3250 if (flag == PEER_FLAG_SHUTDOWN)
3251 return BGP_ERR_PEER_GROUP_SHUTDOWN;
3252 else
3253 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3254 }
3255
3256 /* Flag conflict check. */
3257 if (set
3258 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
3259 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
3260 return BGP_ERR_PEER_FLAG_CONFLICT;
3261
3262 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3263 {
3264 if (set && CHECK_FLAG (peer->flags, flag) == flag)
3265 return 0;
3266 if (! set && ! CHECK_FLAG (peer->flags, flag))
3267 return 0;
3268 }
3269
3270 if (set)
3271 SET_FLAG (peer->flags, flag);
3272 else
3273 UNSET_FLAG (peer->flags, flag);
3274
3275 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3276 {
3277 if (action.type == peer_change_reset)
3278 peer_flag_modify_action (peer, flag);
3279
3280 return 0;
3281 }
3282
3283 /* peer-group member updates. */
3284 group = peer->group;
3285
1eb8ef25 3286 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3287 {
3288 if (set && CHECK_FLAG (peer->flags, flag) == flag)
3289 continue;
3290
3291 if (! set && ! CHECK_FLAG (peer->flags, flag))
3292 continue;
3293
3294 if (set)
3295 SET_FLAG (peer->flags, flag);
3296 else
3297 UNSET_FLAG (peer->flags, flag);
3298
3299 if (action.type == peer_change_reset)
3300 peer_flag_modify_action (peer, flag);
3301 }
3302 return 0;
3303}
3304
3305int
3306peer_flag_set (struct peer *peer, u_int32_t flag)
3307{
3308 return peer_flag_modify (peer, flag, 1);
3309}
3310
3311int
3312peer_flag_unset (struct peer *peer, u_int32_t flag)
3313{
3314 return peer_flag_modify (peer, flag, 0);
3315}
3316
94f2b392 3317static int
718e3744 3318peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
3319{
3320 if (peer->af_group[afi][safi])
3321 return 1;
3322 return 0;
3323}
3324
94f2b392 3325static int
718e3744 3326peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
3327 int set)
3328{
3329 int found;
3330 int size;
1eb8ef25 3331 struct listnode *node, *nnode;
718e3744 3332 struct peer_group *group;
3333 struct peer_flag_action action;
3334
3335 memset (&action, 0, sizeof (struct peer_flag_action));
3336 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
3337
3338 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
3339
3340 /* No flag action is found. */
3341 if (! found)
3342 return BGP_ERR_INVALID_FLAG;
3343
3344 /* Adress family must be activated. */
3345 if (! peer->afc[afi][safi])
3346 return BGP_ERR_PEER_INACTIVE;
3347
3348 /* Not for peer-group member. */
3349 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
3350 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3351
3352 /* Spcecial check for reflector client. */
3353 if (flag & PEER_FLAG_REFLECTOR_CLIENT
3354 && peer_sort (peer) != BGP_PEER_IBGP)
3355 return BGP_ERR_NOT_INTERNAL_PEER;
3356
3357 /* Spcecial check for remove-private-AS. */
3358 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
3359 && peer_sort (peer) == BGP_PEER_IBGP)
3360 return BGP_ERR_REMOVE_PRIVATE_AS;
3361
c7122e14
DS
3362 /* as-override is not allowed for IBGP peers */
3363 if (flag & PEER_FLAG_AS_OVERRIDE
3364 && peer_sort (peer) == BGP_PEER_IBGP)
3365 return BGP_ERR_AS_OVERRIDE;
3366
718e3744 3367 /* When unset the peer-group member's flag we have to check
3368 peer-group configuration. */
3369 if (! set && peer->af_group[afi][safi])
3370 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
3371 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3372
3373 /* When current flag configuration is same as requested one. */
3374 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3375 {
3376 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
3377 return 0;
3378 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
3379 return 0;
3380 }
3381
3382 if (set)
3383 SET_FLAG (peer->af_flags[afi][safi], flag);
3384 else
3385 UNSET_FLAG (peer->af_flags[afi][safi], flag);
3386
3387 /* Execute action when peer is established. */
3388 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3389 && peer->status == Established)
3390 {
3391 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
3392 bgp_clear_adj_in (peer, afi, safi);
3393 else
e0701b79 3394 {
3395 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3396 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3397 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3398 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3399 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3400 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3401 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3402 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3403
3404 peer_change_action (peer, afi, safi, action.type);
3405 }
3406
718e3744 3407 }
3408
3409 /* Peer group member updates. */
3410 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3411 {
3412 group = peer->group;
3413
1eb8ef25 3414 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3415 {
3416 if (! peer->af_group[afi][safi])
3417 continue;
3418
3419 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
3420 continue;
3421
3422 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
3423 continue;
3424
3425 if (set)
3426 SET_FLAG (peer->af_flags[afi][safi], flag);
3427 else
3428 UNSET_FLAG (peer->af_flags[afi][safi], flag);
3429
3430 if (peer->status == Established)
3431 {
3432 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
3433 bgp_clear_adj_in (peer, afi, safi);
3434 else
e0701b79 3435 {
3436 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3437 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3438 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3439 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3440 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3441 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3442 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3443 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3444
3445 peer_change_action (peer, afi, safi, action.type);
3446 }
718e3744 3447 }
3448 }
3449 }
3450 return 0;
3451}
3452
3453int
3454peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3455{
3456 return peer_af_flag_modify (peer, afi, safi, flag, 1);
3457}
3458
3459int
3460peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3461{
3462 return peer_af_flag_modify (peer, afi, safi, flag, 0);
3463}
6b0655a2 3464
718e3744 3465/* EBGP multihop configuration. */
3466int
3467peer_ebgp_multihop_set (struct peer *peer, int ttl)
3468{
3469 struct peer_group *group;
1eb8ef25 3470 struct listnode *node, *nnode;
fa411a21 3471 struct peer *peer1;
718e3744 3472
a80beece 3473 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
718e3744 3474 return 0;
3475
fa411a21
NH
3476 /* see comment in peer_ttl_security_hops_set() */
3477 if (ttl != MAXTTL)
3478 {
3479 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3480 {
3481 group = peer->group;
3482 if (group->conf->gtsm_hops != 0)
3483 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3484
3485 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
3486 {
6d85b15b 3487 if (peer1->sort == BGP_PEER_IBGP)
fa411a21
NH
3488 continue;
3489
3490 if (peer1->gtsm_hops != 0)
3491 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3492 }
3493 }
3494 else
3495 {
3496 if (peer->gtsm_hops != 0)
3497 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3498 }
3499 }
3500
718e3744 3501 peer->ttl = ttl;
3502
3503 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3504 {
6d85b15b 3505 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
eb821189 3506 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
718e3744 3507 }
3508 else
3509 {
3510 group = peer->group;
1eb8ef25 3511 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 3512 {
6d85b15b 3513 if (peer->sort == BGP_PEER_IBGP)
eb821189 3514 continue;
718e3744 3515
eb821189 3516 peer->ttl = group->conf->ttl;
718e3744 3517
eb821189 3518 if (peer->fd >= 0)
3519 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
3520 }
718e3744 3521 }
3522 return 0;
3523}
3524
3525int
3526peer_ebgp_multihop_unset (struct peer *peer)
3527{
3528 struct peer_group *group;
1eb8ef25 3529 struct listnode *node, *nnode;
718e3744 3530
6d85b15b 3531 if (peer->sort == BGP_PEER_IBGP)
718e3744 3532 return 0;
3533
fa411a21
NH
3534 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
3535 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3536
718e3744 3537 if (peer_group_active (peer))
3538 peer->ttl = peer->group->conf->ttl;
3539 else
3540 peer->ttl = 1;
3541
3542 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3543 {
6d85b15b 3544 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
eb821189 3545 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
718e3744 3546 }
3547 else
3548 {
3549 group = peer->group;
1eb8ef25 3550 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 3551 {
6d85b15b 3552 if (peer->sort == BGP_PEER_IBGP)
eb821189 3553 continue;
3554
3555 peer->ttl = 1;
3556
3557 if (peer->fd >= 0)
3558 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
3559 }
718e3744 3560 }
3561 return 0;
3562}
6b0655a2 3563
718e3744 3564/* Neighbor description. */
3565int
3566peer_description_set (struct peer *peer, char *desc)
3567{
3568 if (peer->desc)
3569 XFREE (MTYPE_PEER_DESC, peer->desc);
3570
3571 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
3572
3573 return 0;
3574}
3575
3576int
3577peer_description_unset (struct peer *peer)
3578{
3579 if (peer->desc)
3580 XFREE (MTYPE_PEER_DESC, peer->desc);
3581
3582 peer->desc = NULL;
3583
3584 return 0;
3585}
6b0655a2 3586
718e3744 3587/* Neighbor update-source. */
3588int
fd79ac91 3589peer_update_source_if_set (struct peer *peer, const char *ifname)
718e3744 3590{
3591 struct peer_group *group;
1eb8ef25 3592 struct listnode *node, *nnode;
718e3744 3593
3594 if (peer->update_if)
3595 {
3596 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3597 && strcmp (peer->update_if, ifname) == 0)
3598 return 0;
3599
3600 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3601 peer->update_if = NULL;
3602 }
3603
3604 if (peer->update_source)
3605 {
3606 sockunion_free (peer->update_source);
3607 peer->update_source = NULL;
3608 }
3609
3610 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3611
3612 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3613 {
6aa136f1 3614 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3615 {
3616 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3617 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3618 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3619 }
718e3744 3620 else
1ff9a340 3621 bgp_session_reset(peer);
718e3744 3622 return 0;
3623 }
3624
3625 /* peer-group member updates. */
3626 group = peer->group;
1eb8ef25 3627 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3628 {
3629 if (peer->update_if)
3630 {
3631 if (strcmp (peer->update_if, ifname) == 0)
3632 continue;
3633
3634 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3635 peer->update_if = NULL;
3636 }
3637
3638 if (peer->update_source)
3639 {
3640 sockunion_free (peer->update_source);
3641 peer->update_source = NULL;
3642 }
3643
3644 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3645
6aa136f1 3646 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3647 {
3648 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3649 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3650 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3651 }
718e3744 3652 else
1ff9a340 3653 bgp_session_reset(peer);
718e3744 3654 }
3655 return 0;
3656}
3657
3658int
3659peer_update_source_addr_set (struct peer *peer, union sockunion *su)
3660{
3661 struct peer_group *group;
1eb8ef25 3662 struct listnode *node, *nnode;
718e3744 3663
3664 if (peer->update_source)
3665 {
3666 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3667 && sockunion_cmp (peer->update_source, su) == 0)
3668 return 0;
3669 sockunion_free (peer->update_source);
3670 peer->update_source = NULL;
3671 }
3672
3673 if (peer->update_if)
3674 {
3675 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3676 peer->update_if = NULL;
1ff9a340 3677
718e3744 3678 }
3679
3680 peer->update_source = sockunion_dup (su);
3681
3682 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3683 {
6aa136f1 3684 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3685 {
3686 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3687 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3688 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3689 }
718e3744 3690 else
1ff9a340 3691 bgp_session_reset(peer);
718e3744 3692 return 0;
3693 }
3694
3695 /* peer-group member updates. */
3696 group = peer->group;
1eb8ef25 3697 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3698 {
3699 if (peer->update_source)
3700 {
3701 if (sockunion_cmp (peer->update_source, su) == 0)
3702 continue;
3703 sockunion_free (peer->update_source);
3704 peer->update_source = NULL;
3705 }
3706
3707 if (peer->update_if)
3708 {
3709 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3710 peer->update_if = NULL;
3711 }
3712
3713 peer->update_source = sockunion_dup (su);
3714
6aa136f1 3715 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3716 {
3717 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3718 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3719 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3720 }
718e3744 3721 else
1ff9a340 3722 bgp_session_reset(peer);
718e3744 3723 }
3724 return 0;
3725}
3726
3727int
3728peer_update_source_unset (struct peer *peer)
3729{
3730 union sockunion *su;
3731 struct peer_group *group;
1eb8ef25 3732 struct listnode *node, *nnode;
718e3744 3733
3734 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3735 && ! peer->update_source
3736 && ! peer->update_if)
3737 return 0;
3738
3739 if (peer->update_source)
3740 {
3741 sockunion_free (peer->update_source);
3742 peer->update_source = NULL;
3743 }
3744 if (peer->update_if)
3745 {
3746 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3747 peer->update_if = NULL;
3748 }
3749
3750 if (peer_group_active (peer))
3751 {
3752 group = peer->group;
3753
3754 if (group->conf->update_source)
3755 {
3756 su = sockunion_dup (group->conf->update_source);
3757 peer->update_source = su;
3758 }
3759 else if (group->conf->update_if)
3760 peer->update_if =
3761 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3762 }
3763
3764 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3765 {
6aa136f1 3766 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3767 {
3768 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3769 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3770 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3771 }
718e3744 3772 else
1ff9a340 3773 bgp_session_reset(peer);
718e3744 3774 return 0;
3775 }
3776
3777 /* peer-group member updates. */
3778 group = peer->group;
1eb8ef25 3779 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3780 {
3781 if (! peer->update_source && ! peer->update_if)
3782 continue;
3783
3784 if (peer->update_source)
3785 {
3786 sockunion_free (peer->update_source);
3787 peer->update_source = NULL;
3788 }
3789
3790 if (peer->update_if)
3791 {
3792 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3793 peer->update_if = NULL;
3794 }
3795
6aa136f1 3796 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 3797 {
3798 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3799 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3800 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3801 }
718e3744 3802 else
1ff9a340 3803 bgp_session_reset(peer);
718e3744 3804 }
3805 return 0;
3806}
6b0655a2 3807
718e3744 3808int
3809peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
fd79ac91 3810 const char *rmap)
718e3744 3811{
3812 struct peer_group *group;
1eb8ef25 3813 struct listnode *node, *nnode;
718e3744 3814
3815 /* Adress family must be activated. */
3816 if (! peer->afc[afi][safi])
3817 return BGP_ERR_PEER_INACTIVE;
3818
3819 /* Default originate can't be used for peer group memeber. */
3820 if (peer_is_group_member (peer, afi, safi))
3821 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3822
3823 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3824 || (rmap && ! peer->default_rmap[afi][safi].name)
3825 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3826 {
3827 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3828
3829 if (rmap)
3830 {
3831 if (peer->default_rmap[afi][safi].name)
3832 free (peer->default_rmap[afi][safi].name);
3833 peer->default_rmap[afi][safi].name = strdup (rmap);
3834 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3835 }
3836 }
3837
3838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3839 {
3f9c7369
DS
3840 if (peer->status == Established && peer->afc_nego[afi][safi]) {
3841 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 3842 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
3843 bgp_announce_route (peer, afi, safi);
3844 }
718e3744 3845 return 0;
3846 }
3847
3848 /* peer-group member updates. */
3849 group = peer->group;
1eb8ef25 3850 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3851 {
3852 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3853
3854 if (rmap)
3855 {
3856 if (peer->default_rmap[afi][safi].name)
3857 free (peer->default_rmap[afi][safi].name);
3858 peer->default_rmap[afi][safi].name = strdup (rmap);
3859 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3860 }
3861
3f9c7369
DS
3862 if (peer->status == Established && peer->afc_nego[afi][safi]) {
3863 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 3864 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
3865 bgp_announce_route (peer, afi, safi);
3866 }
718e3744 3867 }
3868 return 0;
3869}
3870
3871int
3872peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3873{
3874 struct peer_group *group;
1eb8ef25 3875 struct listnode *node, *nnode;
718e3744 3876
3877 /* Adress family must be activated. */
3878 if (! peer->afc[afi][safi])
3879 return BGP_ERR_PEER_INACTIVE;
3880
3881 /* Default originate can't be used for peer group memeber. */
3882 if (peer_is_group_member (peer, afi, safi))
3883 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3884
3885 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3886 {
3887 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3888
3889 if (peer->default_rmap[afi][safi].name)
3890 free (peer->default_rmap[afi][safi].name);
3891 peer->default_rmap[afi][safi].name = NULL;
3892 peer->default_rmap[afi][safi].map = NULL;
3893 }
3894
3895 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3896 {
3f9c7369
DS
3897 if (peer->status == Established && peer->afc_nego[afi][safi]) {
3898 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 3899 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
3900 bgp_announce_route (peer, afi, safi);
3901 }
718e3744 3902 return 0;
3903 }
3904
3905 /* peer-group member updates. */
3906 group = peer->group;
1eb8ef25 3907 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3908 {
3909 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3910
3911 if (peer->default_rmap[afi][safi].name)
3912 free (peer->default_rmap[afi][safi].name);
3913 peer->default_rmap[afi][safi].name = NULL;
3914 peer->default_rmap[afi][safi].map = NULL;
3915
3f9c7369
DS
3916 if (peer->status == Established && peer->afc_nego[afi][safi]) {
3917 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 3918 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
3919 bgp_announce_route (peer, afi, safi);
3920 }
718e3744 3921 }
3922 return 0;
3923}
6b0655a2 3924
718e3744 3925int
3926peer_port_set (struct peer *peer, u_int16_t port)
3927{
3928 peer->port = port;
3929 return 0;
3930}
3931
3932int
3933peer_port_unset (struct peer *peer)
3934{
3935 peer->port = BGP_PORT_DEFAULT;
3936 return 0;
3937}
6b0655a2 3938
718e3744 3939/* neighbor weight. */
3940int
3941peer_weight_set (struct peer *peer, u_int16_t weight)
3942{
3943 struct peer_group *group;
1eb8ef25 3944 struct listnode *node, *nnode;
718e3744 3945
3946 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3947 peer->weight = weight;
3948
3949 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3950 return 0;
3951
3952 /* peer-group member updates. */
3953 group = peer->group;
1eb8ef25 3954 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3955 {
3956 peer->weight = group->conf->weight;
3957 }
3958 return 0;
3959}
3960
3961int
3962peer_weight_unset (struct peer *peer)
3963{
3964 struct peer_group *group;
1eb8ef25 3965 struct listnode *node, *nnode;
718e3744 3966
3967 /* Set default weight. */
3968 if (peer_group_active (peer))
3969 peer->weight = peer->group->conf->weight;
3970 else
3971 peer->weight = 0;
3972
3973 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3974
3975 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3976 return 0;
3977
3978 /* peer-group member updates. */
3979 group = peer->group;
1eb8ef25 3980 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 3981 {
3982 peer->weight = 0;
3983 }
3984 return 0;
3985}
6b0655a2 3986
718e3744 3987int
3988peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3989{
3990 struct peer_group *group;
1eb8ef25 3991 struct listnode *node, *nnode;
718e3744 3992
3993 /* Not for peer group memeber. */
3994 if (peer_group_active (peer))
3995 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3996
3997 /* keepalive value check. */
3998 if (keepalive > 65535)
3999 return BGP_ERR_INVALID_VALUE;
4000
4001 /* Holdtime value check. */
4002 if (holdtime > 65535)
4003 return BGP_ERR_INVALID_VALUE;
4004
4005 /* Holdtime value must be either 0 or greater than 3. */
4006 if (holdtime < 3 && holdtime != 0)
4007 return BGP_ERR_INVALID_VALUE;
4008
4009 /* Set value to the configuration. */
4010 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4011 peer->holdtime = holdtime;
4012 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4013
4014 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4015 return 0;
4016
4017 /* peer-group member updates. */
4018 group = peer->group;
1eb8ef25 4019 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4020 {
4021 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4022 peer->holdtime = group->conf->holdtime;
4023 peer->keepalive = group->conf->keepalive;
4024 }
4025 return 0;
4026}
4027
4028int
4029peer_timers_unset (struct peer *peer)
4030{
4031 struct peer_group *group;
1eb8ef25 4032 struct listnode *node, *nnode;
718e3744 4033
4034 if (peer_group_active (peer))
4035 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4036
4037 /* Clear configuration. */
4038 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4039 peer->keepalive = 0;
4040 peer->holdtime = 0;
4041
4042 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4043 return 0;
4044
4045 /* peer-group member updates. */
4046 group = peer->group;
1eb8ef25 4047 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4048 {
4049 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4050 peer->holdtime = 0;
4051 peer->keepalive = 0;
4052 }
4053
4054 return 0;
4055}
6b0655a2 4056
718e3744 4057int
4058peer_timers_connect_set (struct peer *peer, u_int32_t connect)
4059{
966f821c
DS
4060 struct peer_group *group;
4061 struct listnode *node, *nnode;
4062
718e3744 4063 if (peer_group_active (peer))
4064 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4065
4066 if (connect > 65535)
4067 return BGP_ERR_INVALID_VALUE;
4068
4069 /* Set value to the configuration. */
4070 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4071 peer->connect = connect;
4072
4073 /* Set value to timer setting. */
4074 peer->v_connect = connect;
4075
966f821c
DS
4076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4077 return 0;
4078
4079 /* peer-group member updates. */
4080 group = peer->group;
4081 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4082 {
4083 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4084 peer->connect = connect;
4085 peer->v_connect = connect;
4086 }
718e3744 4087 return 0;
4088}
4089
4090int
4091peer_timers_connect_unset (struct peer *peer)
4092{
966f821c
DS
4093 struct peer_group *group;
4094 struct listnode *node, *nnode;
4095
718e3744 4096 if (peer_group_active (peer))
4097 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4098
4099 /* Clear configuration. */
4100 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4101 peer->connect = 0;
4102
4103 /* Set timer setting to default value. */
4104 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4105
966f821c
DS
4106 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4107 return 0;
4108
4109 /* peer-group member updates. */
4110 group = peer->group;
4111 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4112 {
4113 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4114 peer->connect = 0;
4115 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4116 }
718e3744 4117 return 0;
4118}
6b0655a2 4119
718e3744 4120int
4121peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
4122{
966f821c
DS
4123 struct peer_group *group;
4124 struct listnode *node, *nnode;
4125
718e3744 4126 if (peer_group_active (peer))
4127 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4128
4129 if (routeadv > 600)
4130 return BGP_ERR_INVALID_VALUE;
4131
4132 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4133 peer->routeadv = routeadv;
4134 peer->v_routeadv = routeadv;
4135
3f9c7369
DS
4136 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4137 update_group_adjust_peer_afs (peer);
4138 if (peer->status == Established)
4139 bgp_announce_route_all (peer);
966f821c 4140 return 0;
3f9c7369 4141 }
966f821c
DS
4142
4143 /* peer-group member updates. */
4144 group = peer->group;
4145 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4146 {
4147 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4148 peer->routeadv = routeadv;
4149 peer->v_routeadv = routeadv;
3f9c7369
DS
4150 update_group_adjust_peer_afs (peer);
4151 if (peer->status == Established)
4152 bgp_announce_route_all (peer);
966f821c
DS
4153 }
4154
718e3744 4155 return 0;
4156}
4157
4158int
4159peer_advertise_interval_unset (struct peer *peer)
4160{
966f821c
DS
4161 struct peer_group *group;
4162 struct listnode *node, *nnode;
4163
718e3744 4164 if (peer_group_active (peer))
4165 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4166
4167 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4168 peer->routeadv = 0;
4169
6d85b15b 4170 if (peer->sort == BGP_PEER_IBGP)
718e3744 4171 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4172 else
4173 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
966f821c 4174
3f9c7369
DS
4175 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4176 update_group_adjust_peer_afs (peer);
4177 if (peer->status == Established)
4178 bgp_announce_route_all (peer);
966f821c 4179 return 0;
3f9c7369 4180 }
966f821c
DS
4181
4182 /* peer-group member updates. */
4183 group = peer->group;
4184 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4185 {
4186 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4187 peer->routeadv = 0;
4188
4189 if (peer->sort == BGP_PEER_IBGP)
4190 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4191 else
4192 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3f9c7369
DS
4193
4194 update_group_adjust_peer_afs (peer);
4195 if (peer->status == Established)
4196 bgp_announce_route_all (peer);
966f821c 4197 }
718e3744 4198
4199 return 0;
4200}
6b0655a2 4201
718e3744 4202/* neighbor interface */
4203int
fd79ac91 4204peer_interface_set (struct peer *peer, const char *str)
718e3744 4205{
4206 if (peer->ifname)
4207 free (peer->ifname);
4208 peer->ifname = strdup (str);
4209
4210 return 0;
4211}
4212
4213int
4214peer_interface_unset (struct peer *peer)
4215{
4216 if (peer->ifname)
4217 free (peer->ifname);
4218 peer->ifname = NULL;
4219
4220 return 0;
4221}
6b0655a2 4222
718e3744 4223/* Allow-as in. */
4224int
4225peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
4226{
4227 struct peer_group *group;
1eb8ef25 4228 struct listnode *node, *nnode;
718e3744 4229
4230 if (allow_num < 1 || allow_num > 10)
4231 return BGP_ERR_INVALID_VALUE;
4232
4233 if (peer->allowas_in[afi][safi] != allow_num)
4234 {
4235 peer->allowas_in[afi][safi] = allow_num;
4236 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
4237 peer_change_action (peer, afi, safi, peer_change_reset_in);
4238 }
4239
4240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4241 return 0;
4242
4243 group = peer->group;
1eb8ef25 4244 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4245 {
4246 if (peer->allowas_in[afi][safi] != allow_num)
4247 {
4248 peer->allowas_in[afi][safi] = allow_num;
4249 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
4250 peer_change_action (peer, afi, safi, peer_change_reset_in);
4251 }
4252
4253 }
4254 return 0;
4255}
4256
4257int
4258peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
4259{
4260 struct peer_group *group;
1eb8ef25 4261 struct listnode *node, *nnode;
718e3744 4262
4263 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4264 {
4265 peer->allowas_in[afi][safi] = 0;
4266 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4267 }
4268
4269 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4270 return 0;
4271
4272 group = peer->group;
1eb8ef25 4273 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4274 {
4275 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4276 {
4277 peer->allowas_in[afi][safi] = 0;
4278 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4279 }
4280 }
4281 return 0;
4282}
6b0655a2 4283
718e3744 4284int
9d3f9705 4285peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
718e3744 4286{
4287 struct bgp *bgp = peer->bgp;
4288 struct peer_group *group;
1eb8ef25 4289 struct listnode *node, *nnode;
718e3744 4290
4291 if (peer_sort (peer) != BGP_PEER_EBGP
4292 && peer_sort (peer) != BGP_PEER_INTERNAL)
4293 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4294
4295 if (bgp->as == as)
4296 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4297
4298 if (peer_group_active (peer))
4299 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4300
9d3f9705
AC
4301 if (peer->as == as)
4302 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4303
718e3744 4304 if (peer->change_local_as == as &&
4305 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
9d3f9705
AC
4306 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
4307 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
4308 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
718e3744 4309 return 0;
4310
4311 peer->change_local_as = as;
4312 if (no_prepend)
4313 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4314 else
4315 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4316
9d3f9705
AC
4317 if (replace_as)
4318 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4319 else
4320 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4321
718e3744 4322 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4323 {
6aa136f1 4324 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4325 {
4326 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4327 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4328 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4329 }
718e3744 4330 else
1ff9a340 4331 bgp_session_reset(peer);
718e3744 4332 return 0;
4333 }
4334
4335 group = peer->group;
1eb8ef25 4336 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4337 {
4338 peer->change_local_as = as;
4339 if (no_prepend)
4340 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4341 else
4342 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4343
9d3f9705
AC
4344 if (replace_as)
4345 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4346 else
4347 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4348
6aa136f1 4349 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4350 {
4351 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4352 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4353 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4354 }
718e3744 4355 else
4356 BGP_EVENT_ADD (peer, BGP_Stop);
4357 }
4358
4359 return 0;
4360}
4361
4362int
4363peer_local_as_unset (struct peer *peer)
4364{
4365 struct peer_group *group;
1eb8ef25 4366 struct listnode *node, *nnode;
718e3744 4367
4368 if (peer_group_active (peer))
4369 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4370
4371 if (! peer->change_local_as)
4372 return 0;
4373
4374 peer->change_local_as = 0;
4375 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4376 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4377
4378 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4379 {
6aa136f1 4380 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4381 {
4382 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4383 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4384 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4385 }
718e3744 4386 else
4387 BGP_EVENT_ADD (peer, BGP_Stop);
4388
4389 return 0;
4390 }
4391
4392 group = peer->group;
1eb8ef25 4393 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4394 {
4395 peer->change_local_as = 0;
4396 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4397 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4398
6aa136f1 4399 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4400 {
4401 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4402 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4403 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4404 }
718e3744 4405 else
1ff9a340 4406 bgp_session_reset(peer);
718e3744 4407 }
4408 return 0;
4409}
6b0655a2 4410
0df7c91f
PJ
4411/* Set password for authenticating with the peer. */
4412int
4413peer_password_set (struct peer *peer, const char *password)
4414{
4415 struct listnode *nn, *nnode;
4416 int len = password ? strlen(password) : 0;
4417 int ret = BGP_SUCCESS;
4418
4419 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
4420 return BGP_ERR_INVALID_VALUE;
4421
4422 if (peer->password && strcmp (peer->password, password) == 0
4423 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4424 return 0;
4425
4426 if (peer->password)
4427 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4428
4429 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
4430
4431 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4432 {
6aa136f1
VS
4433 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4434 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
0df7c91f 4435 else
1ff9a340 4436 bgp_session_reset(peer);
0df7c91f
PJ
4437
4438 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
4439 }
4440
4441 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
4442 {
4443 if (peer->password && strcmp (peer->password, password) == 0)
4444 continue;
4445
4446 if (peer->password)
4447 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4448
4449 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4450
6aa136f1 4451 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4452 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4453 else
1ff9a340 4454 bgp_session_reset(peer);
0df7c91f
PJ
4455
4456 if (bgp_md5_set (peer) < 0)
4457 ret = BGP_ERR_TCPSIG_FAILED;
4458 }
4459
4460 return ret;
4461}
4462
4463int
4464peer_password_unset (struct peer *peer)
4465{
4466 struct listnode *nn, *nnode;
4467
4468 if (!peer->password
4469 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4470 return 0;
4471
4472 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4473 {
4474 if (peer_group_active (peer)
4475 && peer->group->conf->password
4476 && strcmp (peer->group->conf->password, peer->password) == 0)
4477 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
4478
6aa136f1 4479 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4480 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4481 else
1ff9a340 4482 bgp_session_reset(peer);
0df7c91f
PJ
4483
4484 if (peer->password)
4485 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4486
4487 peer->password = NULL;
4488
4489 bgp_md5_set (peer);
4490
4491 return 0;
4492 }
4493
4494 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4495 peer->password = NULL;
4496
4497 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
4498 {
4499 if (!peer->password)
4500 continue;
4501
6aa136f1 4502 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4503 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4504 else
1ff9a340 4505 bgp_session_reset(peer);
0df7c91f
PJ
4506
4507 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4508 peer->password = NULL;
4509
4510 bgp_md5_set (peer);
4511 }
4512
4513 return 0;
4514}
6b0655a2 4515
3f9c7369 4516/*
3f9c7369 4517 * Helper function that is called after the name of the policy
94f34286
DS
4518 * being used by a peer has changed (AF specific). Automatically
4519 * initiates inbound or outbound processing as needed.
3f9c7369
DS
4520 */
4521static void
94f34286 4522peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
3f9c7369 4523{
94f34286 4524 if (outbound)
3f9c7369 4525 {
94f34286
DS
4526 update_group_adjust_peer (peer_af_find (peer, afi, safi));
4527 if (peer->status == Established)
4528 bgp_announce_route(peer, afi, safi);
3f9c7369
DS
4529 }
4530 else
94f34286
DS
4531 {
4532 if (peer->status != Established)
4533 return;
4534
4535 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4536 bgp_soft_reconfig_in (peer, afi, safi);
4537 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4538 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4539 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4540 }
3f9c7369
DS
4541}
4542
4543
718e3744 4544/* Set distribute list to the peer. */
4545int
4546peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 4547 const char *name)
718e3744 4548{
4549 struct bgp_filter *filter;
4550 struct peer_group *group;
1eb8ef25 4551 struct listnode *node, *nnode;
718e3744 4552
4553 if (! peer->afc[afi][safi])
4554 return BGP_ERR_PEER_INACTIVE;
4555
4556 if (direct != FILTER_IN && direct != FILTER_OUT)
4557 return BGP_ERR_INVALID_VALUE;
4558
4559 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4560 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4561
4562 filter = &peer->filter[afi][safi];
4563
4564 if (filter->plist[direct].name)
4565 return BGP_ERR_PEER_FILTER_CONFLICT;
4566
4567 if (filter->dlist[direct].name)
4568 free (filter->dlist[direct].name);
4569 filter->dlist[direct].name = strdup (name);
4570 filter->dlist[direct].alist = access_list_lookup (afi, name);
4571
4572 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4573 {
94f34286
DS
4574 peer_on_policy_change(peer, afi, safi,
4575 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4576 return 0;
4577 }
718e3744 4578
4579 group = peer->group;
1eb8ef25 4580 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4581 {
4582 filter = &peer->filter[afi][safi];
4583
4584 if (! peer->af_group[afi][safi])
4585 continue;
4586
4587 if (filter->dlist[direct].name)
4588 free (filter->dlist[direct].name);
4589 filter->dlist[direct].name = strdup (name);
4590 filter->dlist[direct].alist = access_list_lookup (afi, name);
94f34286
DS
4591 peer_on_policy_change(peer, afi, safi,
4592 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4593 }
4594
4595 return 0;
4596}
4597
4598int
4599peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4600{
4601 struct bgp_filter *filter;
4602 struct bgp_filter *gfilter;
4603 struct peer_group *group;
1eb8ef25 4604 struct listnode *node, *nnode;
718e3744 4605
4606 if (! peer->afc[afi][safi])
4607 return BGP_ERR_PEER_INACTIVE;
4608
4609 if (direct != FILTER_IN && direct != FILTER_OUT)
4610 return BGP_ERR_INVALID_VALUE;
4611
4612 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4613 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4614
4615 filter = &peer->filter[afi][safi];
4616
4617 /* apply peer-group filter */
4618 if (peer->af_group[afi][safi])
4619 {
4620 gfilter = &peer->group->conf->filter[afi][safi];
4621
4622 if (gfilter->dlist[direct].name)
4623 {
4624 if (filter->dlist[direct].name)
4625 free (filter->dlist[direct].name);
4626 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
4627 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
94f34286
DS
4628 peer_on_policy_change(peer, afi, safi,
4629 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4630 return 0;
4631 }
4632 }
4633
4634 if (filter->dlist[direct].name)
4635 free (filter->dlist[direct].name);
4636 filter->dlist[direct].name = NULL;
4637 filter->dlist[direct].alist = NULL;
4638
4639 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4640 {
94f34286
DS
4641 peer_on_policy_change(peer, afi, safi,
4642 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4643 return 0;
4644 }
718e3744 4645
94f34286
DS
4646 group = peer->group;
4647 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4648 {
4649 filter = &peer->filter[afi][safi];
718e3744 4650
94f34286
DS
4651 if (! peer->af_group[afi][safi])
4652 continue;
718e3744 4653
94f34286
DS
4654 if (filter->dlist[direct].name)
4655 free (filter->dlist[direct].name);
4656 filter->dlist[direct].name = NULL;
4657 filter->dlist[direct].alist = NULL;
4658 peer_on_policy_change(peer, afi, safi,
4659 (direct == FILTER_OUT) ? 1 : 0);
4660 }
718e3744 4661
4662 return 0;
4663}
4664
4665/* Update distribute list. */
94f2b392 4666static void
718e3744 4667peer_distribute_update (struct access_list *access)
4668{
4669 afi_t afi;
4670 safi_t safi;
4671 int direct;
1eb8ef25 4672 struct listnode *mnode, *mnnode;
4673 struct listnode *node, *nnode;
718e3744 4674 struct bgp *bgp;
4675 struct peer *peer;
4676 struct peer_group *group;
4677 struct bgp_filter *filter;
4678
1eb8ef25 4679 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 4680 {
3f9c7369
DS
4681 if (access->name)
4682 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name,
4683 0, 0);
1eb8ef25 4684 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 4685 {
4686 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4687 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4688 {
4689 filter = &peer->filter[afi][safi];
4690
4691 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4692 {
4693 if (filter->dlist[direct].name)
4694 filter->dlist[direct].alist =
4695 access_list_lookup (afi, filter->dlist[direct].name);
4696 else
4697 filter->dlist[direct].alist = NULL;
4698 }
4699 }
4700 }
1eb8ef25 4701 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 4702 {
4703 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4704 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4705 {
4706 filter = &group->conf->filter[afi][safi];
4707
4708 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4709 {
4710 if (filter->dlist[direct].name)
4711 filter->dlist[direct].alist =
4712 access_list_lookup (afi, filter->dlist[direct].name);
4713 else
4714 filter->dlist[direct].alist = NULL;
4715 }
4716 }
4717 }
4718 }
4719}
6b0655a2 4720
718e3744 4721/* Set prefix list to the peer. */
4722int
4723peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 4724 const char *name)
718e3744 4725{
4726 struct bgp_filter *filter;
4727 struct peer_group *group;
1eb8ef25 4728 struct listnode *node, *nnode;
718e3744 4729
4730 if (! peer->afc[afi][safi])
4731 return BGP_ERR_PEER_INACTIVE;
4732
4733 if (direct != FILTER_IN && direct != FILTER_OUT)
4734 return BGP_ERR_INVALID_VALUE;
4735
4736 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4737 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4738
4739 filter = &peer->filter[afi][safi];
4740
4741 if (filter->dlist[direct].name)
4742 return BGP_ERR_PEER_FILTER_CONFLICT;
4743
4744 if (filter->plist[direct].name)
4745 free (filter->plist[direct].name);
4746 filter->plist[direct].name = strdup (name);
4747 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4748
4749 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4750 {
94f34286
DS
4751 peer_on_policy_change(peer, afi, safi,
4752 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4753 return 0;
4754 }
718e3744 4755
4756 group = peer->group;
1eb8ef25 4757 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4758 {
4759 filter = &peer->filter[afi][safi];
4760
4761 if (! peer->af_group[afi][safi])
4762 continue;
4763
4764 if (filter->plist[direct].name)
4765 free (filter->plist[direct].name);
4766 filter->plist[direct].name = strdup (name);
4767 filter->plist[direct].plist = prefix_list_lookup (afi, name);
94f34286
DS
4768 peer_on_policy_change(peer, afi, safi,
4769 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4770 }
4771 return 0;
4772}
4773
4774int
4775peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4776{
4777 struct bgp_filter *filter;
4778 struct bgp_filter *gfilter;
4779 struct peer_group *group;
1eb8ef25 4780 struct listnode *node, *nnode;
718e3744 4781
4782 if (! peer->afc[afi][safi])
4783 return BGP_ERR_PEER_INACTIVE;
4784
4785 if (direct != FILTER_IN && direct != FILTER_OUT)
4786 return BGP_ERR_INVALID_VALUE;
4787
4788 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4789 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4790
4791 filter = &peer->filter[afi][safi];
4792
4793 /* apply peer-group filter */
4794 if (peer->af_group[afi][safi])
4795 {
4796 gfilter = &peer->group->conf->filter[afi][safi];
4797
4798 if (gfilter->plist[direct].name)
4799 {
4800 if (filter->plist[direct].name)
4801 free (filter->plist[direct].name);
4802 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4803 filter->plist[direct].plist = gfilter->plist[direct].plist;
94f34286
DS
4804 peer_on_policy_change(peer, afi, safi,
4805 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4806 return 0;
4807 }
4808 }
4809
4810 if (filter->plist[direct].name)
4811 free (filter->plist[direct].name);
4812 filter->plist[direct].name = NULL;
4813 filter->plist[direct].plist = NULL;
4814
4815 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4816 {
94f34286
DS
4817 peer_on_policy_change(peer, afi, safi,
4818 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4819 return 0;
4820 }
718e3744 4821
4822 group = peer->group;
1eb8ef25 4823 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4824 {
4825 filter = &peer->filter[afi][safi];
4826
4827 if (! peer->af_group[afi][safi])
4828 continue;
4829
4830 if (filter->plist[direct].name)
4831 free (filter->plist[direct].name);
4832 filter->plist[direct].name = NULL;
4833 filter->plist[direct].plist = NULL;
94f34286
DS
4834 peer_on_policy_change(peer, afi, safi,
4835 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4836 }
4837
4838 return 0;
4839}
4840
4841/* Update prefix-list list. */
94f2b392 4842static void
718e3744 4843peer_prefix_list_update (struct prefix_list *plist)
4844{
1eb8ef25 4845 struct listnode *mnode, *mnnode;
4846 struct listnode *node, *nnode;
718e3744 4847 struct bgp *bgp;
4848 struct peer *peer;
4849 struct peer_group *group;
4850 struct bgp_filter *filter;
4851 afi_t afi;
4852 safi_t safi;
4853 int direct;
4854
1eb8ef25 4855 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 4856 {
3f9c7369
DS
4857
4858 /*
4859 * Update the prefix-list on update groups.
4860 */
4861 update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST,
4862 plist ? plist->name : NULL, 0, 0);
4863
1eb8ef25 4864 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 4865 {
4866 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4867 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4868 {
4869 filter = &peer->filter[afi][safi];
4870
4871 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4872 {
4873 if (filter->plist[direct].name)
4874 filter->plist[direct].plist =
4875 prefix_list_lookup (afi, filter->plist[direct].name);
4876 else
4877 filter->plist[direct].plist = NULL;
4878 }
4879 }
4880 }
1eb8ef25 4881 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 4882 {
4883 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4884 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4885 {
4886 filter = &group->conf->filter[afi][safi];
4887
4888 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4889 {
4890 if (filter->plist[direct].name)
4891 filter->plist[direct].plist =
4892 prefix_list_lookup (afi, filter->plist[direct].name);
4893 else
4894 filter->plist[direct].plist = NULL;
4895 }
4896 }
4897 }
4898 }
4899}
6b0655a2 4900
718e3744 4901int
4902peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 4903 const char *name)
718e3744 4904{
4905 struct bgp_filter *filter;
4906 struct peer_group *group;
1eb8ef25 4907 struct listnode *node, *nnode;
718e3744 4908
4909 if (! peer->afc[afi][safi])
4910 return BGP_ERR_PEER_INACTIVE;
4911
4912 if (direct != FILTER_IN && direct != FILTER_OUT)
4913 return BGP_ERR_INVALID_VALUE;
4914
4915 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4916 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4917
4918 filter = &peer->filter[afi][safi];
4919
4920 if (filter->aslist[direct].name)
4921 free (filter->aslist[direct].name);
4922 filter->aslist[direct].name = strdup (name);
4923 filter->aslist[direct].aslist = as_list_lookup (name);
4924
4925 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4926 {
94f34286
DS
4927 peer_on_policy_change(peer, afi, safi,
4928 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4929 return 0;
4930 }
718e3744 4931
4932 group = peer->group;
1eb8ef25 4933 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4934 {
4935 filter = &peer->filter[afi][safi];
4936
4937 if (! peer->af_group[afi][safi])
4938 continue;
4939
4940 if (filter->aslist[direct].name)
4941 free (filter->aslist[direct].name);
4942 filter->aslist[direct].name = strdup (name);
4943 filter->aslist[direct].aslist = as_list_lookup (name);
94f34286
DS
4944 peer_on_policy_change(peer, afi, safi,
4945 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4946 }
4947 return 0;
4948}
4949
4950int
4951peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4952{
4953 struct bgp_filter *filter;
4954 struct bgp_filter *gfilter;
4955 struct peer_group *group;
1eb8ef25 4956 struct listnode *node, *nnode;
718e3744 4957
4958 if (! peer->afc[afi][safi])
4959 return BGP_ERR_PEER_INACTIVE;
4960
b5f29603 4961 if (direct != FILTER_IN && direct != FILTER_OUT)
718e3744 4962 return BGP_ERR_INVALID_VALUE;
4963
b5f29603 4964 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
718e3744 4965 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4966
4967 filter = &peer->filter[afi][safi];
4968
4969 /* apply peer-group filter */
4970 if (peer->af_group[afi][safi])
4971 {
4972 gfilter = &peer->group->conf->filter[afi][safi];
4973
4974 if (gfilter->aslist[direct].name)
4975 {
4976 if (filter->aslist[direct].name)
4977 free (filter->aslist[direct].name);
4978 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4979 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
94f34286
DS
4980 peer_on_policy_change(peer, afi, safi,
4981 (direct == FILTER_OUT) ? 1 : 0);
718e3744 4982 return 0;
4983 }
4984 }
4985
4986 if (filter->aslist[direct].name)
4987 free (filter->aslist[direct].name);
4988 filter->aslist[direct].name = NULL;
4989 filter->aslist[direct].aslist = NULL;
4990
4991 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 4992 {
94f34286
DS
4993 peer_on_policy_change(peer, afi, safi,
4994 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
4995 return 0;
4996 }
718e3744 4997
4998 group = peer->group;
1eb8ef25 4999 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5000 {
5001 filter = &peer->filter[afi][safi];
5002
5003 if (! peer->af_group[afi][safi])
5004 continue;
5005
5006 if (filter->aslist[direct].name)
5007 free (filter->aslist[direct].name);
5008 filter->aslist[direct].name = NULL;
5009 filter->aslist[direct].aslist = NULL;
94f34286
DS
5010 peer_on_policy_change(peer, afi, safi,
5011 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5012 }
5013
5014 return 0;
5015}
5016
94f2b392 5017static void
518f0eb1 5018peer_aslist_update (char *aslist_name)
718e3744 5019{
5020 afi_t afi;
5021 safi_t safi;
5022 int direct;
1eb8ef25 5023 struct listnode *mnode, *mnnode;
5024 struct listnode *node, *nnode;
718e3744 5025 struct bgp *bgp;
5026 struct peer *peer;
5027 struct peer_group *group;
5028 struct bgp_filter *filter;
5029
1eb8ef25 5030 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5031 {
3f9c7369
DS
5032 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name,
5033 0, 0);
5034
1eb8ef25 5035 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5036 {
5037 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5038 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5039 {
5040 filter = &peer->filter[afi][safi];
5041
5042 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5043 {
5044 if (filter->aslist[direct].name)
5045 filter->aslist[direct].aslist =
5046 as_list_lookup (filter->aslist[direct].name);
5047 else
5048 filter->aslist[direct].aslist = NULL;
5049 }
5050 }
5051 }
1eb8ef25 5052 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5053 {
5054 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5055 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5056 {
5057 filter = &group->conf->filter[afi][safi];
5058
5059 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5060 {
5061 if (filter->aslist[direct].name)
5062 filter->aslist[direct].aslist =
5063 as_list_lookup (filter->aslist[direct].name);
5064 else
5065 filter->aslist[direct].aslist = NULL;
5066 }
5067 }
5068 }
5069 }
5070}
3f9c7369 5071
518f0eb1
DS
5072static void
5073peer_aslist_add (char *aslist_name)
5074{
5075 peer_aslist_update (aslist_name);
5076 route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED);
5077}
5078
5079static void
5080peer_aslist_del (char *aslist_name)
5081{
5082 peer_aslist_update (aslist_name);
5083 route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_DELETED);
5084}
5085
6b0655a2 5086
718e3744 5087int
5088peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5089 const char *name)
718e3744 5090{
5091 struct bgp_filter *filter;
5092 struct peer_group *group;
1eb8ef25 5093 struct listnode *node, *nnode;
718e3744 5094
5095 if (! peer->afc[afi][safi])
5096 return BGP_ERR_PEER_INACTIVE;
5097
fee0f4c6 5098 if (direct != RMAP_IN && direct != RMAP_OUT &&
5099 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
718e3744 5100 return BGP_ERR_INVALID_VALUE;
5101
fee0f4c6 5102 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
5103 && peer_is_group_member (peer, afi, safi))
718e3744 5104 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5105
5106 filter = &peer->filter[afi][safi];
5107
5108 if (filter->map[direct].name)
5109 free (filter->map[direct].name);
518f0eb1 5110
718e3744 5111 filter->map[direct].name = strdup (name);
5112 filter->map[direct].map = route_map_lookup_by_name (name);
5113
5114 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5115 {
94f34286
DS
5116 peer_on_policy_change(peer, afi, safi,
5117 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5118 return 0;
5119 }
718e3744 5120
5121 group = peer->group;
1eb8ef25 5122 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5123 {
5124 filter = &peer->filter[afi][safi];
5125
5126 if (! peer->af_group[afi][safi])
5127 continue;
5128
5129 if (filter->map[direct].name)
5130 free (filter->map[direct].name);
5131 filter->map[direct].name = strdup (name);
5132 filter->map[direct].map = route_map_lookup_by_name (name);
94f34286
DS
5133 peer_on_policy_change(peer, afi, safi,
5134 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5135 }
5136 return 0;
5137}
5138
5139/* Unset route-map from the peer. */
5140int
5141peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5142{
5143 struct bgp_filter *filter;
5144 struct bgp_filter *gfilter;
5145 struct peer_group *group;
1eb8ef25 5146 struct listnode *node, *nnode;
718e3744 5147
5148 if (! peer->afc[afi][safi])
5149 return BGP_ERR_PEER_INACTIVE;
5150
b5f29603 5151 if (direct != RMAP_IN && direct != RMAP_OUT &&
5152 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
718e3744 5153 return BGP_ERR_INVALID_VALUE;
5154
b5f29603 5155 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
5156 && peer_is_group_member (peer, afi, safi))
718e3744 5157 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5158
5159 filter = &peer->filter[afi][safi];
5160
5161 /* apply peer-group filter */
5162 if (peer->af_group[afi][safi])
5163 {
5164 gfilter = &peer->group->conf->filter[afi][safi];
5165
5166 if (gfilter->map[direct].name)
5167 {
5168 if (filter->map[direct].name)
5169 free (filter->map[direct].name);
5170 filter->map[direct].name = strdup (gfilter->map[direct].name);
5171 filter->map[direct].map = gfilter->map[direct].map;
94f34286
DS
5172 peer_on_policy_change(peer, afi, safi,
5173 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5174 return 0;
5175 }
5176 }
5177
5178 if (filter->map[direct].name)
5179 free (filter->map[direct].name);
5180 filter->map[direct].name = NULL;
5181 filter->map[direct].map = NULL;
5182
5183 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5184 {
94f34286
DS
5185 peer_on_policy_change(peer, afi, safi,
5186 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5187 return 0;
5188 }
718e3744 5189
5190 group = peer->group;
1eb8ef25 5191 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5192 {
5193 filter = &peer->filter[afi][safi];
5194
5195 if (! peer->af_group[afi][safi])
5196 continue;
5197
5198 if (filter->map[direct].name)
5199 free (filter->map[direct].name);
5200 filter->map[direct].name = NULL;
5201 filter->map[direct].map = NULL;
94f34286
DS
5202 peer_on_policy_change(peer, afi, safi,
5203 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5204 }
5205 return 0;
5206}
6b0655a2 5207
718e3744 5208/* Set unsuppress-map to the peer. */
5209int
fd79ac91 5210peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
5211 const char *name)
718e3744 5212{
5213 struct bgp_filter *filter;
5214 struct peer_group *group;
1eb8ef25 5215 struct listnode *node, *nnode;
718e3744 5216
5217 if (! peer->afc[afi][safi])
5218 return BGP_ERR_PEER_INACTIVE;
5219
5220 if (peer_is_group_member (peer, afi, safi))
5221 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5222
5223 filter = &peer->filter[afi][safi];
5224
5225 if (filter->usmap.name)
5226 free (filter->usmap.name);
5227
5228 filter->usmap.name = strdup (name);
5229 filter->usmap.map = route_map_lookup_by_name (name);
5230
5231 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5232 {
94f34286 5233 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5234 return 0;
5235 }
718e3744 5236
5237 group = peer->group;
1eb8ef25 5238 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5239 {
5240 filter = &peer->filter[afi][safi];
5241
5242 if (! peer->af_group[afi][safi])
5243 continue;
5244
5245 if (filter->usmap.name)
5246 free (filter->usmap.name);
5247 filter->usmap.name = strdup (name);
5248 filter->usmap.map = route_map_lookup_by_name (name);
94f34286 5249 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5250 }
5251 return 0;
5252}
5253
5254/* Unset route-map from the peer. */
5255int
5256peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
5257{
5258 struct bgp_filter *filter;
5259 struct peer_group *group;
1eb8ef25 5260 struct listnode *node, *nnode;
718e3744 5261
5262 if (! peer->afc[afi][safi])
5263 return BGP_ERR_PEER_INACTIVE;
5264
5265 if (peer_is_group_member (peer, afi, safi))
5266 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
5267
5268 filter = &peer->filter[afi][safi];
5269
5270 if (filter->usmap.name)
5271 free (filter->usmap.name);
5272 filter->usmap.name = NULL;
5273 filter->usmap.map = NULL;
5274
5275 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5276 {
94f34286 5277 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5278 return 0;
5279 }
718e3744 5280
5281 group = peer->group;
1eb8ef25 5282 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5283 {
5284 filter = &peer->filter[afi][safi];
5285
5286 if (! peer->af_group[afi][safi])
5287 continue;
5288
5289 if (filter->usmap.name)
5290 free (filter->usmap.name);
5291 filter->usmap.name = NULL;
5292 filter->usmap.map = NULL;
94f34286 5293 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5294 }
5295 return 0;
5296}
6b0655a2 5297
718e3744 5298int
5299peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
0a486e5f 5300 u_int32_t max, u_char threshold,
5301 int warning, u_int16_t restart)
718e3744 5302{
5303 struct peer_group *group;
1eb8ef25 5304 struct listnode *node, *nnode;
718e3744 5305
5306 if (! peer->afc[afi][safi])
5307 return BGP_ERR_PEER_INACTIVE;
5308
5309 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5310 peer->pmax[afi][safi] = max;
e0701b79 5311 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 5312 peer->pmax_restart[afi][safi] = restart;
718e3744 5313 if (warning)
5314 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5315 else
5316 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5317
fc9a856f 5318 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
718e3744 5319 {
fc9a856f
DS
5320 group = peer->group;
5321 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5322 {
5323 if (! peer->af_group[afi][safi])
5324 continue;
718e3744 5325
fc9a856f
DS
5326 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5327 peer->pmax[afi][safi] = max;
5328 peer->pmax_threshold[afi][safi] = threshold;
5329 peer->pmax_restart[afi][safi] = restart;
5330 if (warning)
5331 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5332 else
5333 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5334
5335 if ((peer->status == Established) && (peer->afc[afi][safi]))
5336 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
5337 }
5338 }
5339 else
5340 {
5341 if ((peer->status == Established) && (peer->afc[afi][safi]))
5342 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
718e3744 5343 }
fc9a856f 5344
718e3744 5345 return 0;
5346}
5347
5348int
5349peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
5350{
5351 struct peer_group *group;
1eb8ef25 5352 struct listnode *node, *nnode;
718e3744 5353
5354 if (! peer->afc[afi][safi])
5355 return BGP_ERR_PEER_INACTIVE;
5356
5357 /* apply peer-group config */
5358 if (peer->af_group[afi][safi])
5359 {
5360 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5361 PEER_FLAG_MAX_PREFIX))
5362 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5363 else
5364 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5365
5366 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5367 PEER_FLAG_MAX_PREFIX_WARNING))
5368 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5369 else
5370 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5371
5372 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
e0701b79 5373 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
0a486e5f 5374 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
718e3744 5375 return 0;
5376 }
5377
5378 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5379 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5380 peer->pmax[afi][safi] = 0;
0a486e5f 5381 peer->pmax_threshold[afi][safi] = 0;
5382 peer->pmax_restart[afi][safi] = 0;
718e3744 5383
5384 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5385 return 0;
5386
5387 group = peer->group;
1eb8ef25 5388 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5389 {
5390 if (! peer->af_group[afi][safi])
5391 continue;
5392
5393 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5394 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5395 peer->pmax[afi][safi] = 0;
0a486e5f 5396 peer->pmax_threshold[afi][safi] = 0;
5397 peer->pmax_restart[afi][safi] = 0;
718e3744 5398 }
5399 return 0;
5400}
5f9adb5d
DL
5401
5402static int is_ebgp_multihop_configured (struct peer *peer)
5403{
5404 struct peer_group *group;
5405 struct listnode *node, *nnode;
5406 struct peer *peer1;
5407
5408 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5409 {
5410 group = peer->group;
5d804b43
PM
5411 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5412 (group->conf->ttl != 1))
5f9adb5d
DL
5413 return 1;
5414
5415 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
5416 {
5d804b43
PM
5417 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
5418 (peer1->ttl != 1))
5f9adb5d
DL
5419 return 1;
5420 }
5421 }
5422 else
5423 {
5d804b43
PM
5424 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5425 (peer->ttl != 1))
5f9adb5d
DL
5426 return 1;
5427 }
5428 return 0;
5429}
5430
fa411a21
NH
5431/* Set # of hops between us and BGP peer. */
5432int
5433peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
5434{
5435 struct peer_group *group;
5436 struct listnode *node, *nnode;
fa411a21
NH
5437 int ret;
5438
5439 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
5440
fa411a21
NH
5441 /* We cannot configure ttl-security hops when ebgp-multihop is already
5442 set. For non peer-groups, the check is simple. For peer-groups, it's
5443 slightly messy, because we need to check both the peer-group structure
5444 and all peer-group members for any trace of ebgp-multihop configuration
5445 before actually applying the ttl-security rules. Cisco really made a
5446 mess of this configuration parameter, and OpenBGPD got it right.
5447 */
89b6d1f8 5448
5f9adb5d
DL
5449 if (peer->gtsm_hops == 0)
5450 {
5451 if (is_ebgp_multihop_configured (peer))
5452 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
fa411a21 5453
5f9adb5d 5454 /* specify MAXTTL on outgoing packets */
5d804b43 5455 /* Routine handles iBGP peers correctly */
5f9adb5d
DL
5456 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5457 if (ret != 0)
5458 return ret;
5459 }
89b6d1f8 5460
fa411a21
NH
5461 peer->gtsm_hops = gtsm_hops;
5462
fa411a21
NH
5463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5464 {
5d804b43 5465 if (peer->fd >= 0)
1ff9a340
DS
5466 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5467 MAXTTL + 1 - gtsm_hops);
5468 if (peer->status != Established && peer->doppelganger)
5469 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5470 MAXTTL + 1 - gtsm_hops);
fa411a21
NH
5471 }
5472 else
5473 {
5474 group = peer->group;
5475 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5476 {
fa411a21
NH
5477 peer->gtsm_hops = group->conf->gtsm_hops;
5478
f5a4827d
SH
5479 /* Change setting of existing peer
5480 * established then change value (may break connectivity)
5481 * not established yet (teardown session and restart)
5482 * no session then do nothing (will get handled by next connection)
5483 */
5484 if (peer->status == Established)
5485 {
5486 if (peer->fd >= 0 && peer->gtsm_hops != 0)
5487 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5488 MAXTTL + 1 - peer->gtsm_hops);
5489 }
5490 else if (peer->status < Established)
5491 {
16286195 5492 if (bgp_debug_neighbor_events(peer))
f5a4827d 5493 zlog_debug ("%s Min-ttl changed", peer->host);
1ff9a340 5494 bgp_session_reset(peer);
f5a4827d 5495 }
fa411a21
NH
5496 }
5497 }
5498
5499 return 0;
5500}
5501
5502int
5503peer_ttl_security_hops_unset (struct peer *peer)
5504{
5505 struct peer_group *group;
5506 struct listnode *node, *nnode;
5507 struct peer *opeer;
5508
5509 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
5510
fa411a21
NH
5511 /* if a peer-group member, then reset to peer-group default rather than 0 */
5512 if (peer_group_active (peer))
5513 peer->gtsm_hops = peer->group->conf->gtsm_hops;
5514 else
5515 peer->gtsm_hops = 0;
5516
5517 opeer = peer;
5518 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5519 {
5d804b43 5520 if (peer->fd >= 0)
fa411a21 5521 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340
DS
5522
5523 if (peer->status != Established && peer->doppelganger)
5524 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, 0);
fa411a21
NH
5525 }
5526 else
5527 {
5528 group = peer->group;
5529 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5530 {
fa411a21
NH
5531 peer->gtsm_hops = 0;
5532
5533 if (peer->fd >= 0)
5534 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340
DS
5535
5536 if (peer->status != Established && peer->doppelganger)
5537 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, 0);
fa411a21
NH
5538 }
5539 }
5540
5541 return peer_ebgp_multihop_unset (opeer);
5542}
6b0655a2 5543
1ff9a340
DS
5544/*
5545 * If peer clear is invoked in a loop for all peers on the BGP instance,
5546 * it may end up freeing the doppelganger, and if this was the next node
5547 * to the current node, we would end up accessing the freed next node.
5548 * Pass along additional parameter which can be updated if next node
5549 * is freed; only required when walking the peer list on BGP instance.
5550 */
718e3744 5551int
1ff9a340 5552peer_clear (struct peer *peer, struct listnode **nnode)
718e3744 5553{
5554 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5555 {
0a486e5f 5556 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5557 {
5558 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
5559 if (peer->t_pmax_restart)
5560 {
5561 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 5562 if (bgp_debug_neighbor_events(peer))
0a486e5f 5563 zlog_debug ("%s Maximum-prefix restart timer canceled",
5564 peer->host);
5565 }
5566 BGP_EVENT_ADD (peer, BGP_Start);
5567 return 0;
5568 }
5569
718e3744 5570 peer->v_start = BGP_INIT_START_TIMER;
6aa136f1 5571 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 5572 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5573 BGP_NOTIFY_CEASE_ADMIN_RESET);
5574 else
1ff9a340 5575 bgp_session_reset_safe(peer, nnode);
718e3744 5576 }
5577 return 0;
5578}
5579
5580int
5581peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
5582 enum bgp_clear_type stype)
5583{
5584 if (peer->status != Established)
5585 return 0;
5586
5587 if (! peer->afc[afi][safi])
5588 return BGP_ERR_AF_UNCONFIGURED;
5589
fee0f4c6 5590 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
5591 {
5592 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
5593 return 0;
5594 bgp_check_local_routes_rsclient (peer, afi, safi);
5595 bgp_soft_reconfig_rsclient (peer, afi, safi);
5596 }
5597
718e3744 5598 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
5599 bgp_announce_route (peer, afi, safi);
5600
5601 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
5602 {
5603 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
5604 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
5605 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
5606 {
5607 struct bgp_filter *filter = &peer->filter[afi][safi];
5608 u_char prefix_type;
5609
5610 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
5611 prefix_type = ORF_TYPE_PREFIX;
5612 else
5613 prefix_type = ORF_TYPE_PREFIX_OLD;
5614
5615 if (filter->plist[FILTER_IN].plist)
5616 {
5617 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
5618 bgp_route_refresh_send (peer, afi, safi,
5619 prefix_type, REFRESH_DEFER, 1);
5620 bgp_route_refresh_send (peer, afi, safi, prefix_type,
5621 REFRESH_IMMEDIATE, 0);
5622 }
5623 else
5624 {
5625 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
5626 bgp_route_refresh_send (peer, afi, safi,
5627 prefix_type, REFRESH_IMMEDIATE, 1);
5628 else
5629 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
5630 }
5631 return 0;
5632 }
5633 }
5634
5635 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
5636 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
5637 {
5638 /* If neighbor has soft reconfiguration inbound flag.
5639 Use Adj-RIB-In database. */
5640 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5641 bgp_soft_reconfig_in (peer, afi, safi);
5642 else
5643 {
5644 /* If neighbor has route refresh capability, send route refresh
5645 message to the peer. */
5646 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
5647 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
5648 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
5649 else
5650 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
5651 }
5652 }
5653 return 0;
5654}
6b0655a2 5655
fd79ac91 5656/* Display peer uptime.*/
5657/* XXX: why does this function return char * when it takes buffer? */
718e3744 5658char *
5659peer_uptime (time_t uptime2, char *buf, size_t len)
5660{
5661 time_t uptime1;
5662 struct tm *tm;
5663
5664 /* Check buffer length. */
5665 if (len < BGP_UPTIME_LEN)
5666 {
0cd1c32d 5667 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
fd79ac91 5668 /* XXX: should return status instead of buf... */
5669 snprintf (buf, len, "<error> ");
5670 return buf;
718e3744 5671 }
5672
5673 /* If there is no connection has been done before print `never'. */
5674 if (uptime2 == 0)
5675 {
5676 snprintf (buf, len, "never ");
5677 return buf;
5678 }
5679
5680 /* Get current time. */
65957886 5681 uptime1 = bgp_clock ();
718e3744 5682 uptime1 -= uptime2;
5683 tm = gmtime (&uptime1);
5684
5685 /* Making formatted timer strings. */
5686#define ONE_DAY_SECOND 60*60*24
5687#define ONE_WEEK_SECOND 60*60*24*7
5688
5689 if (uptime1 < ONE_DAY_SECOND)
5690 snprintf (buf, len, "%02d:%02d:%02d",
5691 tm->tm_hour, tm->tm_min, tm->tm_sec);
5692 else if (uptime1 < ONE_WEEK_SECOND)
5693 snprintf (buf, len, "%dd%02dh%02dm",
5694 tm->tm_yday, tm->tm_hour, tm->tm_min);
5695 else
5696 snprintf (buf, len, "%02dw%dd%02dh",
5697 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
5698 return buf;
5699}
6b0655a2 5700
94f2b392 5701static void
718e3744 5702bgp_config_write_filter (struct vty *vty, struct peer *peer,
5703 afi_t afi, safi_t safi)
5704{
5705 struct bgp_filter *filter;
5706 struct bgp_filter *gfilter = NULL;
5707 char *addr;
5708 int in = FILTER_IN;
5709 int out = FILTER_OUT;
5710
5711 addr = peer->host;
5712 filter = &peer->filter[afi][safi];
5713 if (peer->af_group[afi][safi])
5714 gfilter = &peer->group->conf->filter[afi][safi];
5715
5716 /* distribute-list. */
5717 if (filter->dlist[in].name)
5718 if (! gfilter || ! gfilter->dlist[in].name
5719 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
5720 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
5721 filter->dlist[in].name, VTY_NEWLINE);
5722 if (filter->dlist[out].name && ! gfilter)
5723 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
5724 filter->dlist[out].name, VTY_NEWLINE);
5725
5726 /* prefix-list. */
5727 if (filter->plist[in].name)
5728 if (! gfilter || ! gfilter->plist[in].name
5729 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
5730 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
5731 filter->plist[in].name, VTY_NEWLINE);
5732 if (filter->plist[out].name && ! gfilter)
5733 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
5734 filter->plist[out].name, VTY_NEWLINE);
5735
5736 /* route-map. */
fee0f4c6 5737 if (filter->map[RMAP_IN].name)
5738 if (! gfilter || ! gfilter->map[RMAP_IN].name
5739 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
718e3744 5740 vty_out (vty, " neighbor %s route-map %s in%s", addr,
fee0f4c6 5741 filter->map[RMAP_IN].name, VTY_NEWLINE);
5742 if (filter->map[RMAP_OUT].name && ! gfilter)
718e3744 5743 vty_out (vty, " neighbor %s route-map %s out%s", addr,
fee0f4c6 5744 filter->map[RMAP_OUT].name, VTY_NEWLINE);
5745 if (filter->map[RMAP_IMPORT].name && ! gfilter)
5746 vty_out (vty, " neighbor %s route-map %s import%s", addr,
5747 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
5748 if (filter->map[RMAP_EXPORT].name)
5749 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
5750 || strcmp (filter->map[RMAP_EXPORT].name,
5751 gfilter->map[RMAP_EXPORT].name) != 0)
5752 vty_out (vty, " neighbor %s route-map %s export%s", addr,
5753 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
718e3744 5754
5755 /* unsuppress-map */
5756 if (filter->usmap.name && ! gfilter)
5757 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
5758 filter->usmap.name, VTY_NEWLINE);
5759
5760 /* filter-list. */
5761 if (filter->aslist[in].name)
5762 if (! gfilter || ! gfilter->aslist[in].name
5763 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
5764 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
5765 filter->aslist[in].name, VTY_NEWLINE);
5766 if (filter->aslist[out].name && ! gfilter)
5767 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
5768 filter->aslist[out].name, VTY_NEWLINE);
5769}
5770
5771/* BGP peer configuration display function. */
94f2b392 5772static void
718e3744 5773bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
5774 struct peer *peer, afi_t afi, safi_t safi)
5775{
718e3744 5776 struct peer *g_peer = NULL;
5777 char buf[SU_ADDRSTRLEN];
5778 char *addr;
5779
f14e6fdb
DS
5780 /* Skip dynamic neighbors. */
5781 if (peer_dynamic_neighbor (peer))
5782 return;
5783
a80beece
DS
5784 if (peer->conf_if)
5785 addr = peer->conf_if;
5786 else
5787 addr = peer->host;
5788
718e3744 5789 if (peer_group_active (peer))
5790 g_peer = peer->group->conf;
5791
5792 /************************************
5793 ****** Global to the neighbor ******
5794 ************************************/
5795 if (afi == AFI_IP && safi == SAFI_UNICAST)
5796 {
a80beece
DS
5797 if (peer->conf_if)
5798 vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE);
5799
718e3744 5800 /* remote-as. */
5801 if (! peer_group_active (peer))
5802 {
5803 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5804 vty_out (vty, " neighbor %s peer-group%s", addr,
5805 VTY_NEWLINE);
5806 if (peer->as)
aea339f7 5807 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
718e3744 5808 VTY_NEWLINE);
5809 }
5810 else
5811 {
5812 if (! g_peer->as)
aea339f7 5813 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
718e3744 5814 VTY_NEWLINE);
5815 if (peer->af_group[AFI_IP][SAFI_UNICAST])
5816 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5817 peer->group->name, VTY_NEWLINE);
5818 }
5819
5820 /* local-as. */
5821 if (peer->change_local_as)
5822 if (! peer_group_active (peer))
9d3f9705 5823 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
718e3744 5824 peer->change_local_as,
5825 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
9d3f9705
AC
5826 " no-prepend" : "",
5827 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5828 " replace-as" : "", VTY_NEWLINE);
718e3744 5829
5830 /* Description. */
5831 if (peer->desc)
5832 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5833 VTY_NEWLINE);
5834
5835 /* Shutdown. */
5836 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5837 if (! peer_group_active (peer) ||
5838 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5839 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5840
d5a5c8f0
DS
5841 /* bfd. */
5842 if (CHECK_FLAG (peer->flags, PEER_FLAG_BFD))
5843 if (! peer_group_active (peer) ||
5844 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_BFD))
5845 vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE);
5846
0df7c91f
PJ
5847 /* Password. */
5848 if (peer->password)
5849 if (!peer_group_active (peer)
5850 || ! g_peer->password
5851 || strcmp (peer->password, g_peer->password) != 0)
5852 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5853 VTY_NEWLINE);
5854
3f9c7369
DS
5855 /* neighbor solo */
5856 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
5857 if (!peer_group_active (peer))
5858 vty_out (vty, " neighbor %s solo%s", addr, VTY_NEWLINE);
5859
718e3744 5860 /* BGP port. */
5861 if (peer->port != BGP_PORT_DEFAULT)
0df7c91f 5862 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
718e3744 5863 VTY_NEWLINE);
5864
5865 /* Local interface name. */
5866 if (peer->ifname)
5867 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5868 VTY_NEWLINE);
5869
5870 /* Passive. */
5871 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5872 if (! peer_group_active (peer) ||
5873 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5874 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5875
5876 /* EBGP multihop. */
6d85b15b 5877 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
fa411a21 5878 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
718e3744 5879 if (! peer_group_active (peer) ||
5880 g_peer->ttl != peer->ttl)
5881 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5882 VTY_NEWLINE);
5883
fa411a21 5884 /* ttl-security hops */
5d804b43 5885 if (peer->gtsm_hops != 0)
fa411a21 5886 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
89b6d1f8 5887 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
fa411a21
NH
5888 peer->gtsm_hops, VTY_NEWLINE);
5889
6ffd2079 5890 /* disable-connected-check. */
5891 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
718e3744 5892 if (! peer_group_active (peer) ||
6ffd2079 5893 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5894 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
718e3744 5895
5896 /* Update-source. */
5897 if (peer->update_if)
5898 if (! peer_group_active (peer) || ! g_peer->update_if
5899 || strcmp (g_peer->update_if, peer->update_if) != 0)
5900 vty_out (vty, " neighbor %s update-source %s%s", addr,
5901 peer->update_if, VTY_NEWLINE);
5902 if (peer->update_source)
5903 if (! peer_group_active (peer) || ! g_peer->update_source
5904 || sockunion_cmp (g_peer->update_source,
5905 peer->update_source) != 0)
5906 vty_out (vty, " neighbor %s update-source %s%s", addr,
5907 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5908 VTY_NEWLINE);
5909
718e3744 5910 /* advertisement-interval */
966f821c
DS
5911 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5912 ! peer_group_active (peer))
718e3744 5913 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5914 addr, peer->v_routeadv, VTY_NEWLINE);
5915
5916 /* timers. */
5917 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5918 && ! peer_group_active (peer))
5919 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5920 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5921
966f821c
DS
5922 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5923 ! peer_group_active (peer))
718e3744 5924 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5925 peer->connect, VTY_NEWLINE);
5926
5927 /* Default weight. */
5928 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5929 if (! peer_group_active (peer) ||
5930 g_peer->weight != peer->weight)
5931 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5932 VTY_NEWLINE);
5933
718e3744 5934 /* Dynamic capability. */
5935 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5936 if (! peer_group_active (peer) ||
5937 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5938 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5939 VTY_NEWLINE);
5940
5941 /* dont capability negotiation. */
5942 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5943 if (! peer_group_active (peer) ||
5944 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5945 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5946 VTY_NEWLINE);
5947
5948 /* override capability negotiation. */
5949 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5950 if (! peer_group_active (peer) ||
5951 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5952 vty_out (vty, " neighbor %s override-capability%s", addr,
5953 VTY_NEWLINE);
5954
5955 /* strict capability negotiation. */
5956 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5957 if (! peer_group_active (peer) ||
5958 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5959 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5960 VTY_NEWLINE);
5961
15c71348 5962 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
718e3744 5963 {
5964 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5965 {
5966 if (peer->afc[AFI_IP][SAFI_UNICAST])
5967 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5968 }
5969 else
5970 {
5971 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5972 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5973 }
5974 }
5975 }
5976
5977
5978 /************************************
5979 ****** Per AF to the neighbor ******
5980 ************************************/
5981
5982 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5983 {
5984 if (peer->af_group[afi][safi])
5985 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5986 peer->group->name, VTY_NEWLINE);
5987 else
5988 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5989 }
5990
5991 /* ORF capability. */
5992 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5993 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5994 if (! peer->af_group[afi][safi])
5995 {
5996 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5997
5998 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5999 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
6000 vty_out (vty, " both");
6001 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
6002 vty_out (vty, " send");
6003 else
6004 vty_out (vty, " receive");
6005 vty_out (vty, "%s", VTY_NEWLINE);
6006 }
6007
6008 /* Route reflector client. */
6009 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
6010 && ! peer->af_group[afi][safi])
6011 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
6012 VTY_NEWLINE);
6013
6014 /* Nexthop self. */
6015 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
6016 && ! peer->af_group[afi][safi])
9e7a53c1
TT
6017 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
6018 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
6019 " all" : "", VTY_NEWLINE);
718e3744 6020
5000f21c
DS
6021 /* remove-private-AS */
6022 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi])
6023 {
6024 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) &&
6025 peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
6026 vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE);
6027
6028 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
6029 vty_out (vty, " neighbor %s remove-private-AS replace-AS%s", addr, VTY_NEWLINE);
6030
6031 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
6032 vty_out (vty, " neighbor %s remove-private-AS all%s", addr, VTY_NEWLINE);
6033
6034 else
6035 vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE);
6036 }
718e3744 6037
c7122e14
DS
6038 /* as-override */
6039 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) &&
6040 !peer->af_group[afi][safi])
6041 vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE);
6042
718e3744 6043 /* send-community print. */
6044 if (! peer->af_group[afi][safi])
6045 {
6046 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6047 {
6048 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6049 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6050 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
6051 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6052 vty_out (vty, " neighbor %s send-community extended%s",
6053 addr, VTY_NEWLINE);
6054 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
6055 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
6056 }
6057 else
6058 {
6059 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6060 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6061 vty_out (vty, " no neighbor %s send-community both%s",
6062 addr, VTY_NEWLINE);
6063 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
6064 vty_out (vty, " no neighbor %s send-community extended%s",
6065 addr, VTY_NEWLINE);
6066 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
6067 vty_out (vty, " no neighbor %s send-community%s",
6068 addr, VTY_NEWLINE);
6069 }
6070 }
6071
6072 /* Default information */
6073 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
6074 && ! peer->af_group[afi][safi])
6075 {
6076 vty_out (vty, " neighbor %s default-originate", addr);
6077 if (peer->default_rmap[afi][safi].name)
6078 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
6079 vty_out (vty, "%s", VTY_NEWLINE);
6080 }
6081
6082 /* Soft reconfiguration inbound. */
6083 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6084 if (! peer->af_group[afi][safi] ||
6085 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6086 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
6087 VTY_NEWLINE);
6088
6089 /* maximum-prefix. */
6090 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
6091 if (! peer->af_group[afi][safi]
6092 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
e0701b79 6093 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
718e3744 6094 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
6095 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
e0701b79 6096 {
0a486e5f 6097 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
6098 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6099 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
6100 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
6101 vty_out (vty, " warning-only");
6102 if (peer->pmax_restart[afi][safi])
6103 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
6104 vty_out (vty, "%s", VTY_NEWLINE);
e0701b79 6105 }
718e3744 6106
6107 /* Route server client. */
6108 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
6109 && ! peer->af_group[afi][safi])
6110 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
6111
3cf1288b
DH
6112 /* Nexthop-local unchanged. */
6113 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
6114 && ! peer->af_group[afi][safi])
6115 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
6116
718e3744 6117 /* Allow AS in. */
6118 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
6119 if (! peer_group_active (peer)
6120 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
6121 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
6122 {
6123 if (peer->allowas_in[afi][safi] == 3)
6124 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
6125 else
6126 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
6127 peer->allowas_in[afi][safi], VTY_NEWLINE);
6128 }
6129
6130 /* Filter. */
6131 bgp_config_write_filter (vty, peer, afi, safi);
6132
6133 /* atribute-unchanged. */
6134 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
6135 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
6136 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
6137 && ! peer->af_group[afi][safi])
6138 {
6139 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
6140 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
6141 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
6142 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
6143 else
6144 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
6145 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
6146 " as-path" : "",
6147 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
6148 " next-hop" : "",
6149 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
6150 " med" : "", VTY_NEWLINE);
6151 }
6152}
6153
6154/* Display "address-family" configuration header. */
6155void
6156bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
6157 int *write)
6158{
6159 if (*write)
6160 return;
6161
6162 if (afi == AFI_IP && safi == SAFI_UNICAST)
6163 return;
6164
6165 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
6166
6167 if (afi == AFI_IP)
6168 {
6169 if (safi == SAFI_MULTICAST)
6170 vty_out (vty, "ipv4 multicast");
6171 else if (safi == SAFI_MPLS_VPN)
6172 vty_out (vty, "vpnv4 unicast");
6173 }
6174 else if (afi == AFI_IP6)
37a217a5
PJ
6175 {
6176 vty_out (vty, "ipv6");
6177
6178 if (safi == SAFI_MULTICAST)
6179 vty_out (vty, " multicast");
6180 }
718e3744 6181
6182 vty_out (vty, "%s", VTY_NEWLINE);
6183
6184 *write = 1;
6185}
6186
6187/* Address family based peer configuration display. */
94f2b392 6188static int
718e3744 6189bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
6190 safi_t safi)
6191{
6192 int write = 0;
6193 struct peer *peer;
6194 struct peer_group *group;
1eb8ef25 6195 struct listnode *node, *nnode;
718e3744 6196
6197 bgp_config_write_network (vty, bgp, afi, safi, &write);
6198
6199 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
6200
1eb8ef25 6201 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 6202 {
6203 if (group->conf->afc[afi][safi])
6204 {
6205 bgp_config_write_family_header (vty, afi, safi, &write);
6206 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
6207 }
6208 }
1eb8ef25 6209 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 6210 {
f14e6fdb
DS
6211 /* Skip dynamic neighbors. */
6212 if (peer_dynamic_neighbor (peer))
6213 continue;
6214
718e3744 6215 if (peer->afc[afi][safi])
6216 {
1ff9a340 6217 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
718e3744 6218 {
6219 bgp_config_write_family_header (vty, afi, safi, &write);
6220 bgp_config_write_peer (vty, bgp, peer, afi, safi);
6221 }
6222 }
6223 }
165b5fff
JB
6224
6225 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
73ac8160 6226 bgp_config_write_table_map (vty, bgp, afi, safi, &write);
165b5fff 6227
718e3744 6228 if (write)
6229 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
6230
6231 return write;
6232}
6233
6234int
6235bgp_config_write (struct vty *vty)
6236{
6237 int write = 0;
6238 struct bgp *bgp;
6239 struct peer_group *group;
6240 struct peer *peer;
1eb8ef25 6241 struct listnode *node, *nnode;
6242 struct listnode *mnode, *mnnode;
718e3744 6243
6244 /* BGP Multiple instance. */
6245 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
6246 {
6247 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
6248 write++;
6249 }
6250
6251 /* BGP Config type. */
6252 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6253 {
6254 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
6255 write++;
6256 }
6257
6258 /* BGP configuration. */
1eb8ef25 6259 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 6260 {
6261 if (write)
6262 vty_out (vty, "!%s", VTY_NEWLINE);
6263
6264 /* Router bgp ASN */
aea339f7 6265 vty_out (vty, "router bgp %u", bgp->as);
718e3744 6266
6267 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
6268 {
6269 if (bgp->name)
6270 vty_out (vty, " view %s", bgp->name);
6271 }
6272 vty_out (vty, "%s", VTY_NEWLINE);
6273
6274 /* No Synchronization */
6275 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6276 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
6277
6278 /* BGP fast-external-failover. */
6279 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
6280 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
6281
6282 /* BGP router ID. */
6283 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
6284 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
6285 VTY_NEWLINE);
6286
848973c7 6287 /* BGP log-neighbor-changes. */
6288 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
6289 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
6290
718e3744 6291 /* BGP configuration. */
6292 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
6293 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
6294
6295 /* BGP default ipv4-unicast. */
6296 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6297 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
6298
6299 /* BGP default local-preference. */
6300 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
6301 vty_out (vty, " bgp default local-preference %d%s",
6302 bgp->default_local_pref, VTY_NEWLINE);
6303
3f9c7369
DS
6304 /* BGP default subgroup-pkt-queue-max. */
6305 if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
6306 vty_out (vty, " bgp default subgroup-pkt-queue-max %d%s",
6307 bgp->default_subgroup_pkt_queue_max, VTY_NEWLINE);
6308
718e3744 6309 /* BGP client-to-client reflection. */
6310 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
6311 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
6312
6313 /* BGP cluster ID. */
6314 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
6315 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
6316 VTY_NEWLINE);
6317
907f92c8
DS
6318 /* Disable ebgp connected nexthop check */
6319 if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
6320 vty_out (vty, " bgp disable-ebgp-connected-route-check%s", VTY_NEWLINE);
6321
e0701b79 6322 /* Confederation identifier*/
718e3744 6323 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
e0701b79 6324 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
6325 VTY_NEWLINE);
6326
6327 /* Confederation peer */
6328 if (bgp->confed_peers_cnt > 0)
718e3744 6329 {
e0701b79 6330 int i;
718e3744 6331
e0701b79 6332 vty_out (vty, " bgp confederation peers");
718e3744 6333
e0701b79 6334 for (i = 0; i < bgp->confed_peers_cnt; i++)
aea339f7 6335 vty_out(vty, " %u", bgp->confed_peers[i]);
718e3744 6336
e0701b79 6337 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 6338 }
6339
6340 /* BGP enforce-first-as. */
6341 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
6342 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
6343
6344 /* BGP deterministic-med. */
6345 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
6346 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
538621f2 6347
f188f2c4
DS
6348 /* BGP update-delay. */
6349 bgp_config_write_update_delay (vty, bgp);
6350
abc920f8
DS
6351 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
6352 {
6353 vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
6354 if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
6355 vty_out (vty, " %d", bgp->maxmed_onstartup_value);
6356 vty_out (vty, "%s", VTY_NEWLINE);
6357 }
6358 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
6359 {
6360 vty_out (vty, " bgp max-med administrative");
6361 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
6362 vty_out (vty, " %d", bgp->maxmed_admin_value);
6363 vty_out (vty, "%s", VTY_NEWLINE);
6364 }
6365
cb1faec9
DS
6366 /* write quanta */
6367 bgp_config_write_wpkt_quanta (vty, bgp);
6368
3f9c7369
DS
6369 /* coalesce time */
6370 bgp_config_write_coalesce_time(vty, bgp);
6371
538621f2 6372 /* BGP graceful-restart. */
93406d87 6373 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
6374 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
6375 bgp->stalepath_time, VTY_NEWLINE);
538621f2 6376 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
6377 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
6378
718e3744 6379 /* BGP bestpath method. */
6380 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
6381 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
6811845b 6382 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
6383 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
16fc1eec 6384
2fdd455c 6385 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
16fc1eec
DS
6386 if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_NO_AS_SET)) {
6387 vty_out (vty, " bgp bestpath as-path multipath-relax no-as-set%s", VTY_NEWLINE);
6388 } else {
6389 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
6390 }
2fdd455c 6391 }
16fc1eec 6392
8bd9d948
DS
6393 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6394 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
6395 VTY_NEWLINE);
6396 }
718e3744 6397 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
6398 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
6399 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
6400 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
6401 {
6402 vty_out (vty, " bgp bestpath med");
6403 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
6404 vty_out (vty, " confed");
6405 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
6406 vty_out (vty, " missing-as-worst");
6407 vty_out (vty, "%s", VTY_NEWLINE);
6408 }
6409
6410 /* BGP network import check. */
078430f6
DS
6411 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK_EXACT_MATCH))
6412 vty_out (vty, " bgp network import-check exact%s", VTY_NEWLINE);
6413 else if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
718e3744 6414 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
6415
718e3744 6416 /* BGP flag dampening. */
6417 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
6418 BGP_CONFIG_DAMPENING))
6419 bgp_config_write_damp (vty);
6420
6421 /* BGP static route configuration. */
6422 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
6423
6424 /* BGP redistribute configuration. */
6425 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
6426
6427 /* BGP timers configuration. */
6428 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
6429 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
6430 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
6431 bgp->default_holdtime, VTY_NEWLINE);
6432
518f0eb1
DS
6433 if (bgp->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
6434 vty_out (vty, " bgp route-map delay-timer %d%s", bgp->rmap_update_timer,
6435 VTY_NEWLINE);
6436
718e3744 6437 /* peer-group */
1eb8ef25 6438 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 6439 {
6440 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
6441 }
6442
6443 /* Normal neighbor configuration. */
1eb8ef25 6444 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 6445 {
1ff9a340 6446 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
718e3744 6447 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
6448 }
6449
165b5fff
JB
6450 /* maximum-paths */
6451 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
73ac8160 6452 bgp_config_write_table_map (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
165b5fff 6453
718e3744 6454 /* Distance configuration. */
6455 bgp_config_write_distance (vty, bgp);
6456
f14e6fdb
DS
6457 /* listen range and limit for dynamic BGP neighbors */
6458 bgp_config_write_listen (vty, bgp);
6459
718e3744 6460 /* No auto-summary */
6461 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6462 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
6463
6464 /* IPv4 multicast configuration. */
6465 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
6466
6467 /* IPv4 VPN configuration. */
6468 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
6469
6470 /* IPv6 unicast configuration. */
6471 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
6472
37a217a5
PJ
6473 /* IPv6 multicast configuration. */
6474 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
6475
718e3744 6476 write++;
6477 }
6478 return write;
6479}
6480
6481void
94f2b392 6482bgp_master_init (void)
718e3744 6483{
6484 memset (&bgp_master, 0, sizeof (struct bgp_master));
6485
6486 bm = &bgp_master;
6487 bm->bgp = list_new ();
0df7c91f 6488 bm->listen_sockets = list_new ();
718e3744 6489 bm->port = BGP_PORT_DEFAULT;
6490 bm->master = thread_master_create ();
65957886 6491 bm->start_time = bgp_clock ();
718e3744 6492}
200df115 6493
6b0655a2 6494
718e3744 6495void
94f2b392 6496bgp_init (void)
718e3744 6497{
fc9a856f
DS
6498
6499 /* allocates some vital data structures used by peer commands in vty_init */
6500 bgp_scan_init ();
718e3744 6501
718e3744 6502 /* Init zebra. */
6503 bgp_zebra_init ();
6504
fc9a856f
DS
6505 /* BGP VTY commands installation. */
6506 bgp_vty_init ();
6507
718e3744 6508 /* BGP inits. */
6509 bgp_attr_init ();
6510 bgp_debug_init ();
6511 bgp_dump_init ();
6512 bgp_route_init ();
6513 bgp_route_map_init ();
10f9bf3f 6514 bgp_address_init ();
fc9a856f 6515 bgp_scan_vty_init();
718e3744 6516 bgp_mplsvpn_init ();
6517
6518 /* Access list initialize. */
6519 access_list_init ();
6520 access_list_add_hook (peer_distribute_update);
6521 access_list_delete_hook (peer_distribute_update);
6522
6523 /* Filter list initialize. */
6524 bgp_filter_init ();
518f0eb1
DS
6525 as_list_add_hook (peer_aslist_add);
6526 as_list_delete_hook (peer_aslist_del);
718e3744 6527
6528 /* Prefix list initialize.*/
6529 prefix_list_init ();
6530 prefix_list_add_hook (peer_prefix_list_update);
6531 prefix_list_delete_hook (peer_prefix_list_update);
6532
6533 /* Community list initialize. */
6534 bgp_clist = community_list_init ();
6535
6536#ifdef HAVE_SNMP
6537 bgp_snmp_init ();
6538#endif /* HAVE_SNMP */
6539}
545acafb 6540
6541void
66e5cd87 6542bgp_terminate (void)
545acafb 6543{
545acafb 6544 struct bgp *bgp;
6545 struct peer *peer;
1eb8ef25 6546 struct listnode *node, *nnode;
6547 struct listnode *mnode, *mnnode;
545acafb 6548
1ff9a340
DS
6549 /* Close the listener sockets first as this prevents peers from attempting
6550 * to reconnect on receiving the peer unconfig message. In the presence
6551 * of a large number of peers this will ensure that no peer is left with
6552 * a dangling connection
6553 */
6554 /* reverse bgp_master_init */
6555 bgp_close();
6556 if (bm->listen_sockets)
6557 list_free(bm->listen_sockets);
6558 bm->listen_sockets = NULL;
6559
1eb8ef25 6560 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
6561 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
1ff9a340
DS
6562 if (peer->status == Established ||
6563 peer->status == OpenSent ||
6564 peer->status == OpenConfirm)
545acafb 6565 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
6566 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
1ff9a340 6567
545acafb 6568 bgp_cleanup_routes ();
acde4b86 6569
e210cf9f 6570 if (bm->process_main_queue)
acde4b86
SH
6571 {
6572 work_queue_free (bm->process_main_queue);
6573 bm->process_main_queue = NULL;
6574 }
e210cf9f 6575 if (bm->process_rsclient_queue)
acde4b86
SH
6576 {
6577 work_queue_free (bm->process_rsclient_queue);
6578 bm->process_rsclient_queue = NULL;
6579 }
545acafb 6580}