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