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