]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
bgpd: Fix json output
[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
5c525538
RW
614int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
615 afi_t *afi, 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,
5c525538 629 iana_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
40520c36 749static int peer_hash_same(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++)
a08ca0a7 1845 for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++)
d62a17ae 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) {
ed9fb826 2521 /* When the peer already belongs to a peer-group, check the
d62a17ae 2522 * consistency. */
ed9fb826
DW
2523 if (peer_group_active(peer)) {
2524
2525 /* The peer is already bound to the peer-group,
d8a079e8
DW
2526 * nothing to do
2527 */
ed9fb826
DW
2528 if (strcmp(peer->group->name, group->name) == 0)
2529 return 0;
2530 else
2531 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
2532 }
d62a17ae 2533
2534 /* The peer has not specified a remote-as, inherit it from the
2535 * peer-group */
2536 if (peer->as_type == AS_UNSPECIFIED) {
2537 peer->as_type = group->conf->as_type;
2538 peer->as = group->conf->as;
2539 }
718e3744 2540
d62a17ae 2541 if (!group->conf->as) {
2542 if (peer_sort(group->conf) != BGP_PEER_INTERNAL
2543 && peer_sort(group->conf) != peer_sort(peer)) {
2544 if (as)
2545 *as = peer->as;
2546 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
2547 }
718e3744 2548
d62a17ae 2549 if (peer_sort(group->conf) == BGP_PEER_INTERNAL)
2550 first_member = 1;
2551 }
718e3744 2552
d62a17ae 2553 if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
2554 cap_enhe_preset = 1;
2555
2556 peer_group2peer_config_copy(group, peer);
2557
2558 /*
2559 * Capability extended-nexthop is enabled for an interface
2560 * neighbor by
2561 * default. So, fix that up here.
2562 */
2563 if (peer->conf_if && cap_enhe_preset)
2564 peer_flag_set(peer, PEER_FLAG_CAPABILITY_ENHE);
2565
2566 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2567 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
2568 if (group->conf->afc[afi][safi]) {
2569 peer->afc[afi][safi] = 1;
2570
2571 if (peer_af_find(peer, afi, safi)
2572 || peer_af_create(peer, afi,
2573 safi)) {
2574 peer_group2peer_config_copy_af(
2575 group, peer, afi, safi);
2576 }
2577 } else if (peer->afc[afi][safi])
2578 peer_deactivate(peer, afi, safi);
2579 }
2580
2581 if (peer->group) {
2582 assert(group && peer->group == group);
2583 } else {
2584 struct listnode *pn;
2585 pn = listnode_lookup(bgp->peer, peer);
2586 list_delete_node(bgp->peer, pn);
2587 peer->group = group;
2588 listnode_add_sort(bgp->peer, peer);
2589
2590 peer = peer_lock(peer); /* group->peer list reference */
2591 listnode_add(group->peer, peer);
2592 }
718e3744 2593
d62a17ae 2594 if (first_member) {
2595 /* Advertisement-interval reset */
2596 if (!CHECK_FLAG(group->conf->config,
2597 PEER_CONFIG_ROUTEADV)) {
2598 if (peer_sort(group->conf) == BGP_PEER_IBGP)
2599 group->conf->v_routeadv =
2600 BGP_DEFAULT_IBGP_ROUTEADV;
2601 else
2602 group->conf->v_routeadv =
2603 BGP_DEFAULT_EBGP_ROUTEADV;
2604 }
2605
2606 /* ebgp-multihop reset */
2607 if (peer_sort(group->conf) == BGP_PEER_IBGP)
2608 group->conf->ttl = MAXTTL;
2609
2610 /* local-as reset */
2611 if (peer_sort(group->conf) != BGP_PEER_EBGP) {
2612 group->conf->change_local_as = 0;
2613 UNSET_FLAG(peer->flags,
2614 PEER_FLAG_LOCAL_AS_NO_PREPEND);
2615 UNSET_FLAG(peer->flags,
2616 PEER_FLAG_LOCAL_AS_REPLACE_AS);
2617 }
2618 }
718e3744 2619
d62a17ae 2620 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2621
d62a17ae 2622 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
2623 peer->last_reset = PEER_DOWN_RMAP_BIND;
2624 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2625 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2626 } else {
2627 bgp_session_reset(peer);
2628 }
2629 }
718e3744 2630
d62a17ae 2631 /* Create a new peer. */
2632 else {
2633 if ((group->conf->as_type == AS_SPECIFIED)
2634 && (!group->conf->as)) {
2635 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2636 }
718e3744 2637
d62a17ae 2638 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
2639 group->conf->as_type, 0, 0, group);
718e3744 2640
d62a17ae 2641 peer = peer_lock(peer); /* group->peer list reference */
2642 listnode_add(group->peer, peer);
718e3744 2643
d62a17ae 2644 peer_group2peer_config_copy(group, peer);
a4ed4829 2645
d62a17ae 2646 /* If the peer-group is active for this afi/safi then activate
2647 * for this peer */
2648 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2649 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2650 if (group->conf->afc[afi][safi]) {
2651 peer->afc[afi][safi] = 1;
2652 peer_af_create(peer, afi, safi);
2653 peer_group2peer_config_copy_af(
2654 group, peer, afi, safi);
2655 } else if (peer->afc[afi][safi])
2656 peer_deactivate(peer, afi, safi);
718e3744 2657
d62a17ae 2658 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2659
d62a17ae 2660 /* Set up peer's events and timers. */
2661 if (peer_active(peer))
2662 bgp_timer_set(peer);
2663 }
718e3744 2664
d62a17ae 2665 return 0;
718e3744 2666}
2667
d62a17ae 2668int peer_group_unbind(struct bgp *bgp, struct peer *peer,
2669 struct peer_group *group)
718e3744 2670{
d62a17ae 2671 struct peer *other;
2672 afi_t afi;
2673 safi_t safi;
718e3744 2674
d62a17ae 2675 if (group != peer->group)
2676 return BGP_ERR_PEER_GROUP_MISMATCH;
718e3744 2677
d62a17ae 2678 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2679 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
2680 if (peer->afc[afi][safi]) {
2681 peer->afc[afi][safi] = 0;
2682 peer_af_flag_reset(peer, afi, safi);
718e3744 2683
d62a17ae 2684 if (peer_af_delete(peer, afi, safi) != 0) {
2685 zlog_err(
2686 "couldn't delete af structure for peer %s",
2687 peer->host);
2688 }
2689 }
2690 }
718e3744 2691
d62a17ae 2692 assert(listnode_lookup(group->peer, peer));
2693 peer_unlock(peer); /* peer group list reference */
2694 listnode_delete(group->peer, peer);
2695 peer->group = NULL;
2696 other = peer->doppelganger;
2697
2698 if (group->conf->as) {
2699 peer_delete(peer);
2700 if (other && other->status != Deleted) {
2701 if (other->group) {
2702 peer_unlock(other);
2703 listnode_delete(group->peer, other);
2704 }
2705 other->group = NULL;
2706 peer_delete(other);
2707 }
2708 return 0;
2709 }
718e3744 2710
d62a17ae 2711 bgp_bfd_deregister_peer(peer);
2712 peer_global_config_reset(peer);
718e3744 2713
d62a17ae 2714 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
2715 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2716 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2717 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2718 } else
2719 bgp_session_reset(peer);
c7122e14 2720
718e3744 2721 return 0;
d62a17ae 2722}
718e3744 2723
d62a17ae 2724static int bgp_startup_timer_expire(struct thread *thread)
2725{
2726 struct bgp *bgp;
718e3744 2727
d62a17ae 2728 bgp = THREAD_ARG(thread);
2729 bgp->t_startup = NULL;
718e3744 2730
d62a17ae 2731 return 0;
2732}
e0701b79 2733
d62a17ae 2734/* BGP instance creation by `router bgp' commands. */
2735static struct bgp *bgp_create(as_t *as, const char *name,
2736 enum bgp_instance_type inst_type)
2737{
2738 struct bgp *bgp;
2739 afi_t afi;
2740 safi_t safi;
2741
2742 if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL)
2743 return NULL;
2744
2745 if (BGP_DEBUG(zebra, ZEBRA)) {
2746 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2747 zlog_debug("Creating Default VRF, AS %u", *as);
2748 else
2749 zlog_debug("Creating %s %s, AS %u",
2750 (inst_type == BGP_INSTANCE_TYPE_VRF)
2751 ? "VRF"
2752 : "VIEW",
2753 name, *as);
718e3744 2754 }
adbac85e 2755
d62a17ae 2756 bgp_lock(bgp);
2757 bgp->inst_type = inst_type;
2758 bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
2759 : VRF_UNKNOWN;
2760 bgp->peer_self = peer_new(bgp);
2761 if (bgp->peer_self->host)
2762 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
2763 bgp->peer_self->host =
2764 XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
2765 bgp->peer = list_new();
2766 bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
40520c36
DW
2767 bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
2768 bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
d62a17ae 2769
2770 bgp->group = list_new();
2771 bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
2772
2773 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2774 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
2775 bgp->route[afi][safi] = bgp_table_init(afi, safi);
2776 bgp->aggregate[afi][safi] = bgp_table_init(afi, safi);
2777 bgp->rib[afi][safi] = bgp_table_init(afi, safi);
2778
2779 /* Enable maximum-paths */
2780 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
2781 multipath_num, 0);
2782 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP,
2783 multipath_num, 0);
2784 }
2785
2786 bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
2787 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2788 bgp->default_subgroup_pkt_queue_max =
2789 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
2790 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2791 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
2792 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2793 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
2794 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
2795 bgp->dynamic_neighbors_count = 0;
2796#if DFLT_BGP_IMPORT_CHECK
2797 bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK);
2798#endif
2799#if DFLT_BGP_SHOW_HOSTNAME
2800 bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME);
2801#endif
2802#if DFLT_BGP_LOG_NEIGHBOR_CHANGES
2803 bgp_flag_set(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
2804#endif
2805#if DFLT_BGP_DETERMINISTIC_MED
2806 bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED);
2807#endif
2808 bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
2809
2810 bgp->as = *as;
2811
2812#if ENABLE_BGP_VNC
2813 if (inst_type != BGP_INSTANCE_TYPE_VRF) {
2814 bgp->rfapi = bgp_rfapi_new(bgp);
2815 assert(bgp->rfapi);
2816 assert(bgp->rfapi_cfg);
2817 }
2818#endif /* ENABLE_BGP_VNC */
adbac85e 2819
d62a17ae 2820 if (name) {
2821 bgp->name = XSTRDUP(MTYPE_BGP, name);
2822 } else {
2823 /* TODO - The startup timer needs to be run for the whole of BGP
2824 */
2825 thread_add_timer(bm->master, bgp_startup_timer_expire, bgp,
2826 bgp->restart_time, &bgp->t_startup);
2827 }
06370dac 2828
d62a17ae 2829 bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
2830 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
adbac85e 2831
d62a17ae 2832 QOBJ_REG(bgp, bgp);
adbac85e 2833
d62a17ae 2834 update_bgp_group_init(bgp);
2835 bgp_evpn_init(bgp);
2836 return bgp;
718e3744 2837}
2838
d62a17ae 2839/* Return the "default VRF" instance of BGP. */
2840struct bgp *bgp_get_default(void)
718e3744 2841{
d62a17ae 2842 struct bgp *bgp;
2843 struct listnode *node, *nnode;
2844
2845 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
2846 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2847 return bgp;
2848 return NULL;
718e3744 2849}
2850
d62a17ae 2851/* Lookup BGP entry. */
2852struct bgp *bgp_lookup(as_t as, const char *name)
718e3744 2853{
d62a17ae 2854 struct bgp *bgp;
2855 struct listnode *node, *nnode;
6b0655a2 2856
d62a17ae 2857 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
2858 if (bgp->as == as
2859 && ((bgp->name == NULL && name == NULL)
2860 || (bgp->name && name && strcmp(bgp->name, name) == 0)))
2861 return bgp;
2862 return NULL;
2863}
73d70fa6 2864
d62a17ae 2865/* Lookup BGP structure by view name. */
2866struct bgp *bgp_lookup_by_name(const char *name)
73d70fa6 2867{
d62a17ae 2868 struct bgp *bgp;
2869 struct listnode *node, *nnode;
2870
2871 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
2872 if ((bgp->name == NULL && name == NULL)
2873 || (bgp->name && name && strcmp(bgp->name, name) == 0))
2874 return bgp;
2875 return NULL;
73d70fa6
DL
2876}
2877
d62a17ae 2878/* Lookup BGP instance based on VRF id. */
2879/* Note: Only to be used for incoming messages from Zebra. */
2880struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
73d70fa6 2881{
d62a17ae 2882 struct vrf *vrf;
2883
2884 /* Lookup VRF (in tree) and follow link. */
2885 vrf = vrf_lookup_by_id(vrf_id);
2886 if (!vrf)
2887 return NULL;
2888 return (vrf->info) ? (struct bgp *)vrf->info : NULL;
73d70fa6
DL
2889}
2890
d62a17ae 2891/* Called from VTY commands. */
2892int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
2893 enum bgp_instance_type inst_type)
2894{
2895 struct bgp *bgp;
2896
2897 /* Multiple instance check. */
2898 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
2899 if (name)
2900 bgp = bgp_lookup_by_name(name);
2901 else
2902 bgp = bgp_get_default();
2903
2904 /* Already exists. */
2905 if (bgp) {
2906 if (bgp->as != *as) {
2907 *as = bgp->as;
2908 return BGP_ERR_INSTANCE_MISMATCH;
2909 }
2910 if (bgp->inst_type != inst_type)
2911 return BGP_ERR_INSTANCE_MISMATCH;
2912 *bgp_val = bgp;
2913 return 0;
2914 }
2915 } else {
2916 /* BGP instance name can not be specified for single instance.
2917 */
2918 if (name)
2919 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2920
2921 /* Get default BGP structure if exists. */
2922 bgp = bgp_get_default();
2923
2924 if (bgp) {
2925 if (bgp->as != *as) {
2926 *as = bgp->as;
2927 return BGP_ERR_AS_MISMATCH;
2928 }
2929 *bgp_val = bgp;
2930 return 0;
2931 }
2932 }
73d70fa6 2933
d62a17ae 2934 bgp = bgp_create(as, name, inst_type);
2935 bgp_router_id_set(bgp, &bgp->router_id_zebra);
2936 bgp_address_init(bgp);
db0e1937 2937 bgp_tip_hash_init(bgp);
d62a17ae 2938 bgp_scan_init(bgp);
2939 *bgp_val = bgp;
eb821189 2940
d62a17ae 2941 bgp->t_rmap_def_originate_eval = NULL;
e5cc509c 2942
d62a17ae 2943 /* Create BGP server socket, if first instance. */
2944 if (list_isempty(bm->bgp) && !bgp_option_check(BGP_OPT_NO_LISTEN)) {
2945 if (bgp_socket(bm->port, bm->address) < 0)
2946 return BGP_ERR_INVALID_VALUE;
eb821189 2947 }
6b0655a2 2948
d62a17ae 2949 listnode_add(bm->bgp, bgp);
718e3744 2950
d62a17ae 2951 /* If Default instance or VRF, link to the VRF structure, if present. */
2952 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
2953 || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
2954 struct vrf *vrf;
718e3744 2955
d62a17ae 2956 vrf = bgp_vrf_lookup_by_instance_type(bgp);
2957 if (vrf)
2958 bgp_vrf_link(bgp, vrf);
2959 }
718e3744 2960
d62a17ae 2961 /* Register with Zebra, if needed */
2962 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
2963 bgp_zebra_instance_register(bgp);
718e3744 2964
718e3744 2965
d62a17ae 2966 return 0;
718e3744 2967}
6b0655a2 2968
d62a17ae 2969/*
2970 * Make BGP instance "up". Applies only to VRFs (non-default) and
2971 * implies the VRF has been learnt from Zebra.
2972 */
2973void bgp_instance_up(struct bgp *bgp)
718e3744 2974{
d62a17ae 2975 struct peer *peer;
2976 struct listnode *node, *next;
718e3744 2977
d62a17ae 2978 /* Register with zebra. */
2979 bgp_zebra_instance_register(bgp);
718e3744 2980
d62a17ae 2981 /* Kick off any peers that may have been configured. */
2982 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
2983 if (!BGP_PEER_START_SUPPRESSED(peer))
2984 BGP_EVENT_ADD(peer, BGP_Start);
718e3744 2985 }
2986
d62a17ae 2987 /* Process any networks that have been configured. */
2988 bgp_static_add(bgp);
2989}
2990
2991/*
2992 * Make BGP instance "down". Applies only to VRFs (non-default) and
2993 * implies the VRF has been deleted by Zebra.
2994 */
2995void bgp_instance_down(struct bgp *bgp)
2996{
2997 struct peer *peer;
2998 struct listnode *node;
2999 struct listnode *next;
3000
3001 /* Stop timers. */
3002 if (bgp->t_rmap_def_originate_eval) {
3003 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3004 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3005 why? */
718e3744 3006 }
3007
d62a17ae 3008 /* Bring down peers, so corresponding routes are purged. */
3009 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3010 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3011 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3012 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3013 else
3014 bgp_session_reset(peer);
3015 }
718e3744 3016
d62a17ae 3017 /* Purge network and redistributed routes. */
3018 bgp_purge_static_redist_routes(bgp);
718e3744 3019}
3020
d62a17ae 3021/* Delete BGP instance. */
3022int bgp_delete(struct bgp *bgp)
3023{
3024 struct peer *peer;
3025 struct peer_group *group;
3026 struct listnode *node, *next;
3027 struct vrf *vrf;
3028 afi_t afi;
3029 int i;
3030
3031 THREAD_OFF(bgp->t_startup);
3032
3033 if (BGP_DEBUG(zebra, ZEBRA)) {
3034 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3035 zlog_debug("Deleting Default VRF");
3036 else
3037 zlog_debug("Deleting %s %s",
3038 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3039 ? "VRF"
3040 : "VIEW",
3041 bgp->name);
718e3744 3042 }
3043
d62a17ae 3044 /* Stop timers. */
3045 if (bgp->t_rmap_def_originate_eval) {
3046 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3047 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3048 why? */
718e3744 3049 }
3050
d62a17ae 3051 /* Inform peers we're going down. */
3052 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3053 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3054 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3055 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
718e3744 3056 }
3057
d62a17ae 3058 /* Delete static routes (networks). */
3059 bgp_static_delete(bgp);
6b0655a2 3060
d62a17ae 3061 /* Unset redistribution. */
3062 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3063 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3064 if (i != ZEBRA_ROUTE_BGP)
3065 bgp_redistribute_unset(bgp, afi, i, 0);
718e3744 3066
d62a17ae 3067 /* Free peers and peer-groups. */
3068 for (ALL_LIST_ELEMENTS(bgp->group, node, next, group))
3069 peer_group_delete(group);
718e3744 3070
d62a17ae 3071 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
3072 peer_delete(peer);
3073
3074 if (bgp->peer_self) {
3075 peer_delete(bgp->peer_self);
3076 bgp->peer_self = NULL;
718e3744 3077 }
3078
d62a17ae 3079 update_bgp_group_free(bgp);
718e3744 3080
d62a17ae 3081/* TODO - Other memory may need to be freed - e.g., NHT */
3082
3083#if ENABLE_BGP_VNC
3084 rfapi_delete(bgp);
3085#endif
3086 bgp_cleanup_routes(bgp);
718e3744 3087
d62a17ae 3088 /* Remove visibility via the master list - there may however still be
3089 * routes to be processed still referencing the struct bgp.
3090 */
3091 listnode_delete(bm->bgp, bgp);
718e3744 3092
d62a17ae 3093 /* Deregister from Zebra, if needed */
3094 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3095 bgp_zebra_instance_deregister(bgp);
718e3744 3096
d62a17ae 3097 /* Free interfaces in this instance. */
3098 bgp_if_finish(bgp);
718e3744 3099
d62a17ae 3100 vrf = bgp_vrf_lookup_by_instance_type(bgp);
3101 if (vrf)
3102 bgp_vrf_unlink(bgp, vrf);
718e3744 3103
d62a17ae 3104 thread_master_free_unused(bm->master);
3105 bgp_unlock(bgp); /* initial reference */
718e3744 3106
d62a17ae 3107 return 0;
718e3744 3108}
6b0655a2 3109
d62a17ae 3110static void bgp_free(struct bgp *);
3111
3112void bgp_lock(struct bgp *bgp)
718e3744 3113{
d62a17ae 3114 ++bgp->lock;
718e3744 3115}
3116
d62a17ae 3117void bgp_unlock(struct bgp *bgp)
718e3744 3118{
d62a17ae 3119 assert(bgp->lock > 0);
3120 if (--bgp->lock == 0)
3121 bgp_free(bgp);
718e3744 3122}
6b0655a2 3123
d62a17ae 3124static void bgp_free(struct bgp *bgp)
d93f7ffc 3125{
d62a17ae 3126 afi_t afi;
3127 safi_t safi;
3128 struct bgp_table *table;
3129 struct bgp_node *rn;
d93f7ffc 3130
d62a17ae 3131 QOBJ_UNREG(bgp);
d93f7ffc 3132
d62a17ae 3133 list_delete(bgp->group);
3134 list_delete(bgp->peer);
966f821c 3135
d62a17ae 3136 if (bgp->peerhash) {
3137 hash_free(bgp->peerhash);
3138 bgp->peerhash = NULL;
3139 }
718e3744 3140
d62a17ae 3141 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3142 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
3143 /* Special handling for 2-level routing tables. */
3144 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
3145 || safi == SAFI_EVPN) {
3146 for (rn = bgp_table_top(bgp->rib[afi][safi]);
3147 rn; rn = bgp_route_next(rn)) {
3148 table = (struct bgp_table *)rn->info;
3149 bgp_table_finish(&table);
3150 }
3151 }
3152 if (bgp->route[afi][safi])
3153 bgp_table_finish(&bgp->route[afi][safi]);
3154 if (bgp->aggregate[afi][safi])
3155 bgp_table_finish(&bgp->aggregate[afi][safi]);
3156 if (bgp->rib[afi][safi])
3157 bgp_table_finish(&bgp->rib[afi][safi]);
3158 }
718e3744 3159
d62a17ae 3160 bgp_scan_finish(bgp);
3161 bgp_address_destroy(bgp);
db0e1937 3162 bgp_tip_hash_destroy(bgp);
966f821c 3163
d62a17ae 3164 bgp_evpn_cleanup(bgp);
718e3744 3165
d62a17ae 3166 if (bgp->name)
3167 XFREE(MTYPE_BGP, bgp->name);
966f821c 3168
d62a17ae 3169 XFREE(MTYPE_BGP, bgp);
718e3744 3170}
3171
d62a17ae 3172struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if)
718e3744 3173{
d62a17ae 3174 struct peer *peer;
3175 struct listnode *node, *nnode;
966f821c 3176
d62a17ae 3177 if (!conf_if)
3178 return NULL;
6b0655a2 3179
d62a17ae 3180 if (bgp != NULL) {
3181 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3182 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3183 && !CHECK_FLAG(peer->sflags,
3184 PEER_STATUS_ACCEPT_PEER))
3185 return peer;
3186 } else if (bm->bgp != NULL) {
3187 struct listnode *bgpnode, *nbgpnode;
3188
3189 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3190 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3191 if (peer->conf_if
3192 && !strcmp(peer->conf_if, conf_if)
3193 && !CHECK_FLAG(peer->sflags,
3194 PEER_STATUS_ACCEPT_PEER))
3195 return peer;
3196 }
3197 return NULL;
718e3744 3198}
3199
d62a17ae 3200struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname)
718e3744 3201{
d62a17ae 3202 struct peer *peer;
3203 struct listnode *node, *nnode;
6b0655a2 3204
d62a17ae 3205 if (!hostname)
3206 return NULL;
6b0655a2 3207
d62a17ae 3208 if (bgp != NULL) {
3209 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3210 if (peer->hostname && !strcmp(peer->hostname, hostname)
3211 && !CHECK_FLAG(peer->sflags,
3212 PEER_STATUS_ACCEPT_PEER))
3213 return peer;
3214 } else if (bm->bgp != NULL) {
3215 struct listnode *bgpnode, *nbgpnode;
3216
3217 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3218 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3219 if (peer->hostname
3220 && !strcmp(peer->hostname, hostname)
3221 && !CHECK_FLAG(peer->sflags,
3222 PEER_STATUS_ACCEPT_PEER))
3223 return peer;
3224 }
3225 return NULL;
3226}
3227
3228struct peer *peer_lookup(struct bgp *bgp, union sockunion *su)
3229{
3230 struct peer *peer = NULL;
3231 struct peer tmp_peer;
3232
3233 memset(&tmp_peer, 0, sizeof(struct peer));
3234
3235 /*
3236 * We do not want to find the doppelganger peer so search for the peer
3237 * in
3238 * the hash that has PEER_FLAG_CONFIG_NODE
3239 */
3240 SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3241
3242 tmp_peer.su = *su;
3243
3244 if (bgp != NULL) {
3245 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3246 } else if (bm->bgp != NULL) {
3247 struct listnode *bgpnode, *nbgpnode;
3248
3249 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) {
3250 /* Skip VRFs, this function will not be invoked without
3251 * an instance
3252 * when examining VRFs.
3253 */
3254 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3255 continue;
3256
3257 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3258
3259 if (peer)
3260 break;
3261 }
3262 }
3263
3264 return peer;
3265}
3266
3267struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,
3268 union sockunion *su,
3269 struct peer_group *group)
3270{
3271 struct peer *peer;
3272 afi_t afi;
3273 safi_t safi;
3274
3275 /* Create peer first; we've already checked group config is valid. */
3276 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
3277 group->conf->as_type, 0, 0, group);
3278 if (!peer)
3279 return NULL;
3280
3281 /* Link to group */
3282 peer = peer_lock(peer);
3283 listnode_add(group->peer, peer);
3284
3285 peer_group2peer_config_copy(group, peer);
3286
3287 /*
3288 * Bind peer for all AFs configured for the group. We don't call
3289 * peer_group_bind as that is sub-optimal and does some stuff we don't
3290 * want.
3291 */
3292 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3293 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
3294 if (!group->conf->afc[afi][safi])
3295 continue;
3296 peer->afc[afi][safi] = 1;
3297
3298 if (!peer_af_find(peer, afi, safi))
3299 peer_af_create(peer, afi, safi);
3300
3301 peer_group2peer_config_copy_af(group, peer, afi, safi);
3302 }
3303
3304 /* Mark as dynamic, but also as a "config node" for other things to
3305 * work. */
3306 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3307 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3308
3309 return peer;
3310}
3311
3312struct prefix *
3313peer_group_lookup_dynamic_neighbor_range(struct peer_group *group,
3314 struct prefix *prefix)
3315{
3316 struct listnode *node, *nnode;
3317 struct prefix *range;
3318 afi_t afi;
3319
3320 afi = family2afi(prefix->family);
3321
3322 if (group->listen_range[afi])
3323 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
3324 range))
3325 if (prefix_match(range, prefix))
3326 return range;
3327
3328 return NULL;
3329}
3330
3331struct peer_group *
3332peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix,
3333 struct prefix **listen_range)
3334{
3335 struct prefix *range = NULL;
3336 struct peer_group *group = NULL;
3337 struct listnode *node, *nnode;
3338
3339 *listen_range = NULL;
3340 if (bgp != NULL) {
3341 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3342 if ((range = peer_group_lookup_dynamic_neighbor_range(
3343 group, prefix)))
3344 break;
3345 } else if (bm->bgp != NULL) {
3346 struct listnode *bgpnode, *nbgpnode;
3347
3348 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3349 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3350 if ((range = peer_group_lookup_dynamic_neighbor_range(
3351 group, prefix)))
3352 goto found_range;
3353 }
3354
3355found_range:
3356 *listen_range = range;
3357 return (group && range) ? group : NULL;
3358}
3359
3360struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
3361{
3362 struct peer_group *group;
3363 struct bgp *gbgp;
3364 struct peer *peer;
3365 struct prefix prefix;
3366 struct prefix *listen_range;
3367 int dncount;
3368 char buf[PREFIX2STR_BUFFER];
3369 char buf1[PREFIX2STR_BUFFER];
3370
3371 sockunion2hostprefix(su, &prefix);
3372
3373 /* See if incoming connection matches a configured listen range. */
3374 group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range);
3375
3376 if (!group)
3377 return NULL;
3378
3379
3380 gbgp = group->bgp;
3381
3382 if (!gbgp)
3383 return NULL;
3384
3385 prefix2str(&prefix, buf, sizeof(buf));
3386 prefix2str(listen_range, buf1, sizeof(buf1));
3387
3388 if (bgp_debug_neighbor_events(NULL))
3389 zlog_debug(
3390 "Dynamic Neighbor %s matches group %s listen range %s",
3391 buf, group->name, buf1);
3392
3393 /* Are we within the listen limit? */
3394 dncount = gbgp->dynamic_neighbors_count;
3395
3396 if (dncount >= gbgp->dynamic_neighbors_limit) {
3397 if (bgp_debug_neighbor_events(NULL))
3398 zlog_debug("Dynamic Neighbor %s rejected - at limit %d",
3399 inet_sutop(su, buf),
3400 gbgp->dynamic_neighbors_limit);
3401 return NULL;
3402 }
3403
3404 /* Ensure group is not disabled. */
3405 if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) {
3406 if (bgp_debug_neighbor_events(NULL))
3407 zlog_debug(
3408 "Dynamic Neighbor %s rejected - group %s disabled",
3409 buf, group->name);
3410 return NULL;
3411 }
3412
3413 /* Check that at least one AF is activated for the group. */
3414 if (!peer_group_af_configured(group)) {
3415 if (bgp_debug_neighbor_events(NULL))
3416 zlog_debug(
3417 "Dynamic Neighbor %s rejected - no AF activated for group %s",
3418 buf, group->name);
3419 return NULL;
3420 }
3421
3422 /* Create dynamic peer and bind to associated group. */
3423 peer = peer_create_bind_dynamic_neighbor(gbgp, su, group);
3424 assert(peer);
3425
3426 gbgp->dynamic_neighbors_count = ++dncount;
3427
3428 if (bgp_debug_neighbor_events(peer))
3429 zlog_debug("%s Dynamic Neighbor added, group %s count %d",
3430 peer->host, group->name, dncount);
3431
3432 return peer;
3433}
3434
3435void peer_drop_dynamic_neighbor(struct peer *peer)
3436{
3437 int dncount = -1;
3438 if (peer->group && peer->group->bgp) {
3439 dncount = peer->group->bgp->dynamic_neighbors_count;
3440 if (dncount)
3441 peer->group->bgp->dynamic_neighbors_count = --dncount;
3442 }
3443 if (bgp_debug_neighbor_events(peer))
3444 zlog_debug("%s dropped from group %s, count %d", peer->host,
3445 peer->group->name, dncount);
3446}
3447
3448
3449/* If peer is configured at least one address family return 1. */
3450int peer_active(struct peer *peer)
3451{
3452 if (BGP_PEER_SU_UNSPEC(peer))
3453 return 0;
3454 if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
3455 || peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
3456 || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
3457 || peer->afc[AFI_IP6][SAFI_UNICAST]
3458 || peer->afc[AFI_IP6][SAFI_MULTICAST]
3459 || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
3460 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
3461 || peer->afc[AFI_IP6][SAFI_ENCAP]
3462 || peer->afc[AFI_L2VPN][SAFI_EVPN])
3463 return 1;
3464 return 0;
3465}
3466
3467/* If peer is negotiated at least one address family return 1. */
3468int peer_active_nego(struct peer *peer)
3469{
3470 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3471 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3472 || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
3473 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
3474 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
3475 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
3476 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
3477 || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
3478 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
3479 || peer->afc_nego[AFI_IP6][SAFI_ENCAP]
3480 || peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
3481 return 1;
3482 return 0;
3483}
3484
3485/* peer_flag_change_type. */
3486enum peer_change_type {
3487 peer_change_none,
3488 peer_change_reset,
3489 peer_change_reset_in,
3490 peer_change_reset_out,
3491};
3492
3493static void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
3494 enum peer_change_type type)
3495{
3496 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3497 return;
3498
3499 if (peer->status != Established)
3500 return;
3501
3502 if (type == peer_change_reset) {
3503 /* If we're resetting session, we've to delete both peer struct
3504 */
3505 if ((peer->doppelganger)
3506 && (peer->doppelganger->status != Deleted)
3507 && (!CHECK_FLAG(peer->doppelganger->flags,
3508 PEER_FLAG_CONFIG_NODE)))
3509 peer_delete(peer->doppelganger);
3510
3511 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3512 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3513 } else if (type == peer_change_reset_in) {
3514 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3515 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3516 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0);
3517 else {
3518 if ((peer->doppelganger)
3519 && (peer->doppelganger->status != Deleted)
3520 && (!CHECK_FLAG(peer->doppelganger->flags,
3521 PEER_FLAG_CONFIG_NODE)))
3522 peer_delete(peer->doppelganger);
3523
3524 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3525 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3526 }
3527 } else if (type == peer_change_reset_out) {
3528 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3529 bgp_announce_route(peer, afi, safi);
3530 }
3531}
3532
3533struct peer_flag_action {
3534 /* Peer's flag. */
3535 u_int32_t flag;
3536
3537 /* This flag can be set for peer-group member. */
3538 u_char not_for_member;
3539
3540 /* Action when the flag is changed. */
3541 enum peer_change_type type;
3542
3543 /* Peer down cause */
3544 u_char peer_down;
3545};
3546
3547static const struct peer_flag_action peer_flag_action_list[] = {
3548 {PEER_FLAG_PASSIVE, 0, peer_change_reset},
3549 {PEER_FLAG_SHUTDOWN, 0, peer_change_reset},
3550 {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
3551 {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
3552 {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
3553 {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
3554 {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
3555 {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
3556 {0, 0, 0}};
3557
3558static const struct peer_flag_action peer_af_flag_action_list[] = {
3559 {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out},
3560 {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out},
3561 {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out},
3562 {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out},
3563 {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset},
3564 {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset},
3565 {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in},
3566 {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out},
3567 {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out},
3568 {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out},
3569 // PEER_FLAG_DEFAULT_ORIGINATE
3570 {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out},
3571 {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in},
3572 {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in},
3573 {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset},
3574 {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset},
3575 // PEER_FLAG_MAX_PREFIX
3576 // PEER_FLAG_MAX_PREFIX_WARNING
3577 {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out},
3578 {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out},
3579 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out},
3580 {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
3581 {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
3582 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
3583 {PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset},
3584 {PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset},
3585 {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
3586 {0, 0, 0}};
3587
3588/* Proper action set. */
3589static int peer_flag_action_set(const struct peer_flag_action *action_list,
3590 int size, struct peer_flag_action *action,
3591 u_int32_t flag)
3592{
3593 int i;
3594 int found = 0;
3595 int reset_in = 0;
3596 int reset_out = 0;
3597 const struct peer_flag_action *match = NULL;
3598
3599 /* Check peer's frag action. */
3600 for (i = 0; i < size; i++) {
3601 match = &action_list[i];
3602
3603 if (match->flag == 0)
3604 break;
3605
3606 if (match->flag & flag) {
3607 found = 1;
3608
3609 if (match->type == peer_change_reset_in)
3610 reset_in = 1;
3611 if (match->type == peer_change_reset_out)
3612 reset_out = 1;
3613 if (match->type == peer_change_reset) {
3614 reset_in = 1;
3615 reset_out = 1;
3616 }
3617 if (match->not_for_member)
3618 action->not_for_member = 1;
3619 }
3620 }
3621
3622 /* Set peer clear type. */
3623 if (reset_in && reset_out)
3624 action->type = peer_change_reset;
3625 else if (reset_in)
3626 action->type = peer_change_reset_in;
3627 else if (reset_out)
3628 action->type = peer_change_reset_out;
3629 else
3630 action->type = peer_change_none;
3631
3632 return found;
3633}
3634
3635static void peer_flag_modify_action(struct peer *peer, u_int32_t flag)
3636{
3637 if (flag == PEER_FLAG_SHUTDOWN) {
3638 if (CHECK_FLAG(peer->flags, flag)) {
3639 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
3640 peer_nsf_stop(peer);
3641
3642 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3643 if (peer->t_pmax_restart) {
3644 BGP_TIMER_OFF(peer->t_pmax_restart);
3645 if (bgp_debug_neighbor_events(peer))
3646 zlog_debug(
3647 "%s Maximum-prefix restart timer canceled",
3648 peer->host);
3649 }
3650
3651 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
3652 peer_nsf_stop(peer);
3653
3654 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3655 char *msg = peer->tx_shutdown_message;
3656 size_t msglen;
3657
3658 if (!msg && peer_group_active(peer))
3659 msg = peer->group->conf
3660 ->tx_shutdown_message;
3661 msglen = msg ? strlen(msg) : 0;
3662 if (msglen > 128)
3663 msglen = 128;
3664
3665 if (msglen) {
3666 u_char msgbuf[129];
3667
3668 msgbuf[0] = msglen;
3669 memcpy(msgbuf + 1, msg, msglen);
3670
3671 bgp_notify_send_with_data(
3672 peer, BGP_NOTIFY_CEASE,
3673 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN,
3674 msgbuf, msglen + 1);
3675 } else
3676 bgp_notify_send(
3677 peer, BGP_NOTIFY_CEASE,
3678 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3679 } else
3680 bgp_session_reset(peer);
3681 } else {
3682 peer->v_start = BGP_INIT_START_TIMER;
3683 BGP_EVENT_ADD(peer, BGP_Stop);
3684 }
3685 } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3686 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3687 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3688 else if (flag == PEER_FLAG_PASSIVE)
3689 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
3690 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
3691 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
3692
3693 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3694 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3695 } else
3696 bgp_session_reset(peer);
3697}
3698
3699/* Change specified peer flag. */
3700static int peer_flag_modify(struct peer *peer, u_int32_t flag, int set)
3701{
3702 int found;
3703 int size;
3704 struct peer_group *group;
3705 struct peer *tmp_peer;
3706 struct listnode *node, *nnode;
3707 struct peer_flag_action action;
3708
3709 memset(&action, 0, sizeof(struct peer_flag_action));
3710 size = sizeof peer_flag_action_list / sizeof(struct peer_flag_action);
3711
3712 found = peer_flag_action_set(peer_flag_action_list, size, &action,
3713 flag);
3714
3715 /* No flag action is found. */
3716 if (!found)
3717 return BGP_ERR_INVALID_FLAG;
3718
3719 /* When unset the peer-group member's flag we have to check
3720 peer-group configuration. */
3721 if (!set && peer_group_active(peer))
3722 if (CHECK_FLAG(peer->group->conf->flags, flag)) {
3723 if (flag == PEER_FLAG_SHUTDOWN)
3724 return BGP_ERR_PEER_GROUP_SHUTDOWN;
3725 }
3726
3727 /* Flag conflict check. */
3728 if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
3729 && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
3730 return BGP_ERR_PEER_FLAG_CONFLICT;
3731
3732 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3733 if (set && CHECK_FLAG(peer->flags, flag) == flag)
3734 return 0;
3735 if (!set && !CHECK_FLAG(peer->flags, flag))
3736 return 0;
3737 }
3738
3739 if (set)
3740 SET_FLAG(peer->flags, flag);
3741 else
3742 UNSET_FLAG(peer->flags, flag);
3743
3744 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3745 if (action.type == peer_change_reset)
3746 peer_flag_modify_action(peer, flag);
3747
3748 return 0;
3749 }
3750
3751 /* peer-group member updates. */
3752 group = peer->group;
3753
3754 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
3755
3756 if (set && CHECK_FLAG(tmp_peer->flags, flag) == flag)
3757 continue;
3758
3759 if (!set && !CHECK_FLAG(tmp_peer->flags, flag))
3760 continue;
3761
3762 if (set)
3763 SET_FLAG(tmp_peer->flags, flag);
3764 else
3765 UNSET_FLAG(tmp_peer->flags, flag);
3766
3767 if (action.type == peer_change_reset)
3768 peer_flag_modify_action(tmp_peer, flag);
3769 }
3770 return 0;
3771}
3772
3773int peer_flag_set(struct peer *peer, u_int32_t flag)
3774{
3775 return peer_flag_modify(peer, flag, 1);
3776}
3777
3778int peer_flag_unset(struct peer *peer, u_int32_t flag)
3779{
3780 return peer_flag_modify(peer, flag, 0);
3781}
3782
3783static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
3784 u_int32_t flag, int set)
3785{
3786 int found;
3787 int size;
3788 struct listnode *node, *nnode;
3789 struct peer_group *group;
3790 struct peer_flag_action action;
3791 struct peer *tmp_peer;
3792 struct bgp *bgp;
3793 int addpath_tx_used;
3794
3795 memset(&action, 0, sizeof(struct peer_flag_action));
3796 size = sizeof peer_af_flag_action_list
3797 / sizeof(struct peer_flag_action);
3798
3799 found = peer_flag_action_set(peer_af_flag_action_list, size, &action,
3800 flag);
3801
3802 /* No flag action is found. */
3803 if (!found)
3804 return BGP_ERR_INVALID_FLAG;
3805
3806 /* Special check for reflector client. */
3807 if (flag & PEER_FLAG_REFLECTOR_CLIENT
3808 && peer_sort(peer) != BGP_PEER_IBGP)
3809 return BGP_ERR_NOT_INTERNAL_PEER;
3810
3811 /* Special check for remove-private-AS. */
3812 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
3813 && peer_sort(peer) == BGP_PEER_IBGP)
3814 return BGP_ERR_REMOVE_PRIVATE_AS;
3815
3816 /* as-override is not allowed for IBGP peers */
3817 if (flag & PEER_FLAG_AS_OVERRIDE && peer_sort(peer) == BGP_PEER_IBGP)
3818 return BGP_ERR_AS_OVERRIDE;
3819
3820 /* When current flag configuration is same as requested one. */
3821 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3822 if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag) == flag)
3823 return 0;
3824 if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag))
3825 return 0;
3826 }
3827
3828 if (set)
3829 SET_FLAG(peer->af_flags[afi][safi], flag);
3830 else
3831 UNSET_FLAG(peer->af_flags[afi][safi], flag);
3832
3833 /* Execute action when peer is established. */
3834 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
3835 && peer->status == Established) {
3836 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
3837 bgp_clear_adj_in(peer, afi, safi);
3838 else {
3839 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3840 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3841 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3842 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3843 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3844 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3845 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3846 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3847
3848 peer_change_action(peer, afi, safi, action.type);
3849 }
3850 }
3851
3852 /* Peer group member updates. */
3853 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3854 group = peer->group;
3855
3856 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
3857 if (set
3858 && CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag)
3859 == flag)
3860 continue;
3861
3862 if (!set
3863 && !CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag))
3864 continue;
3865
3866 if (set)
3867 SET_FLAG(tmp_peer->af_flags[afi][safi], flag);
3868 else
3869 UNSET_FLAG(tmp_peer->af_flags[afi][safi], flag);
3870
3871 if (tmp_peer->status == Established) {
3872 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
3873 bgp_clear_adj_in(tmp_peer, afi, safi);
3874 else {
3875 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3876 tmp_peer->last_reset =
3877 PEER_DOWN_RR_CLIENT_CHANGE;
3878 else if (flag
3879 == PEER_FLAG_RSERVER_CLIENT)
3880 tmp_peer->last_reset =
3881 PEER_DOWN_RS_CLIENT_CHANGE;
3882 else if (flag
3883 == PEER_FLAG_ORF_PREFIX_SM)
3884 tmp_peer->last_reset =
3885 PEER_DOWN_CAPABILITY_CHANGE;
3886 else if (flag
3887 == PEER_FLAG_ORF_PREFIX_RM)
3888 tmp_peer->last_reset =
3889 PEER_DOWN_CAPABILITY_CHANGE;
3890
3891 peer_change_action(tmp_peer, afi, safi,
3892 action.type);
3893 }
3894 }
3895 }
3896 }
3897
3898 /* Track if addpath TX is in use */
9d303b37
DL
3899 if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
3900 | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
d62a17ae 3901 bgp = peer->bgp;
3902 addpath_tx_used = 0;
3903
3904 if (set) {
3905 addpath_tx_used = 1;
3906
3907 if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) {
3908 if (!bgp_flag_check(
3909 bgp, BGP_FLAG_DETERMINISTIC_MED)) {
3910 zlog_warn(
3911 "%s: enabling bgp deterministic-med, this is required"
3912 " for addpath-tx-bestpath-per-AS",
3913 peer->host);
3914 bgp_flag_set(
3915 bgp,
3916 BGP_FLAG_DETERMINISTIC_MED);
3917 bgp_recalculate_all_bestpaths(bgp);
3918 }
3919 }
3920 } else {
3921 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode,
3922 tmp_peer)) {
3923 if (CHECK_FLAG(tmp_peer->af_flags[afi][safi],
3924 PEER_FLAG_ADDPATH_TX_ALL_PATHS)
3925 || CHECK_FLAG(
3926 tmp_peer->af_flags[afi][safi],
3927 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
3928 addpath_tx_used = 1;
3929 break;
3930 }
3931 }
3932 }
3933
3934 bgp->addpath_tx_used[afi][safi] = addpath_tx_used;
3935 }
3936
3937 return 0;
3938}
3939
3940int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3941{
3942 return peer_af_flag_modify(peer, afi, safi, flag, 1);
3943}
3944
3945int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi,
3946 u_int32_t flag)
3947{
3948 return peer_af_flag_modify(peer, afi, safi, flag, 0);
3949}
3950
3951
3952int peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
3953{
3954 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
3955 peer->tx_shutdown_message =
3956 msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL;
3957 return 0;
3958}
3959
3960int peer_tx_shutdown_message_unset(struct peer *peer)
3961{
3962 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
3963 return 0;
3964}
3965
3966
3967/* EBGP multihop configuration. */
3968int peer_ebgp_multihop_set(struct peer *peer, int ttl)
3969{
3970 struct peer_group *group;
3971 struct listnode *node, *nnode;
3972 struct peer *peer1;
3973
3974 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
3975 return 0;
3976
3977 /* see comment in peer_ttl_security_hops_set() */
3978 if (ttl != MAXTTL) {
3979 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3980 group = peer->group;
3981 if (group->conf->gtsm_hops != 0)
3982 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3983
3984 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
3985 peer1)) {
3986 if (peer1->sort == BGP_PEER_IBGP)
3987 continue;
3988
3989 if (peer1->gtsm_hops != 0)
3990 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3991 }
3992 } else {
3993 if (peer->gtsm_hops != 0)
3994 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3995 }
3996 }
3997
3998 peer->ttl = ttl;
3999
4000 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4001 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) {
4002 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4003 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4004 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4005 else
4006 bgp_session_reset(peer);
4007 }
4008 } else {
4009 group = peer->group;
4010 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4011 if (peer->sort == BGP_PEER_IBGP)
4012 continue;
4013
4014 peer->ttl = group->conf->ttl;
4015
4016 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4017 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4018 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4019 else
4020 bgp_session_reset(peer);
4021 }
4022 }
4023 return 0;
4024}
4025
4026int peer_ebgp_multihop_unset(struct peer *peer)
4027{
4028 struct peer_group *group;
4029 struct listnode *node, *nnode;
4030
4031 if (peer->sort == BGP_PEER_IBGP)
4032 return 0;
4033
4034 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
4035 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4036
4037 if (peer_group_active(peer))
4038 peer->ttl = peer->group->conf->ttl;
4039 else
4040 peer->ttl = 1;
4041
4042 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4043 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4044 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4045 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4046 else
4047 bgp_session_reset(peer);
4048 } else {
4049 group = peer->group;
4050 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4051 if (peer->sort == BGP_PEER_IBGP)
4052 continue;
4053
4054 peer->ttl = 1;
4055
4056 if (peer->fd >= 0) {
4057 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4058 bgp_notify_send(
4059 peer, BGP_NOTIFY_CEASE,
4060 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4061 else
4062 bgp_session_reset(peer);
4063 }
4064 }
4065 }
4066 return 0;
4067}
4068
4069/* Neighbor description. */
4070int peer_description_set(struct peer *peer, const char *desc)
4071{
4072 if (peer->desc)
4073 XFREE(MTYPE_PEER_DESC, peer->desc);
4074
4075 peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
4076
4077 return 0;
4078}
4079
4080int peer_description_unset(struct peer *peer)
4081{
4082 if (peer->desc)
4083 XFREE(MTYPE_PEER_DESC, peer->desc);
4084
4085 peer->desc = NULL;
4086
4087 return 0;
4088}
4089
4090/* Neighbor update-source. */
4091int peer_update_source_if_set(struct peer *peer, const char *ifname)
4092{
4093 struct peer_group *group;
4094 struct listnode *node, *nnode;
4095
4096 if (peer->update_if) {
4097 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
4098 && strcmp(peer->update_if, ifname) == 0)
4099 return 0;
4100
4101 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4102 peer->update_if = NULL;
4103 }
4104
4105 if (peer->update_source) {
4106 sockunion_free(peer->update_source);
4107 peer->update_source = NULL;
4108 }
4109
4110 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
4111
4112 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4113 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4114 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4115 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4116 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4117 } else
4118 bgp_session_reset(peer);
4119 return 0;
4120 }
4121
4122 /* peer-group member updates. */
4123 group = peer->group;
4124 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4125 if (peer->update_if) {
4126 if (strcmp(peer->update_if, ifname) == 0)
4127 continue;
4128
4129 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4130 peer->update_if = NULL;
4131 }
4132
4133 if (peer->update_source) {
4134 sockunion_free(peer->update_source);
4135 peer->update_source = NULL;
4136 }
4137
4138 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
4139
4140 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4141 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4142 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4143 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4144 } else
4145 bgp_session_reset(peer);
4146 }
4147 return 0;
4148}
4149
4150int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
4151{
4152 struct peer_group *group;
4153 struct listnode *node, *nnode;
4154
4155 if (peer->update_source) {
4156 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
4157 && sockunion_cmp(peer->update_source, su) == 0)
4158 return 0;
4159 sockunion_free(peer->update_source);
4160 peer->update_source = NULL;
4161 }
4162
4163 if (peer->update_if) {
4164 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4165 peer->update_if = NULL;
4166 }
4167
4168 peer->update_source = sockunion_dup(su);
4169
4170 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4171 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4172 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4173 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4174 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4175 } else
4176 bgp_session_reset(peer);
4177 return 0;
4178 }
4179
4180 /* peer-group member updates. */
4181 group = peer->group;
4182 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4183 if (peer->update_source) {
4184 if (sockunion_cmp(peer->update_source, su) == 0)
4185 continue;
4186 sockunion_free(peer->update_source);
4187 peer->update_source = NULL;
4188 }
4189
4190 if (peer->update_if) {
4191 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4192 peer->update_if = NULL;
4193 }
4194
4195 peer->update_source = sockunion_dup(su);
4196
4197 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4198 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4199 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4200 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4201 } else
4202 bgp_session_reset(peer);
4203 }
4204 return 0;
4205}
4206
4207int peer_update_source_unset(struct peer *peer)
4208{
4209 union sockunion *su;
4210 struct peer_group *group;
4211 struct listnode *node, *nnode;
4212
4213 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && !peer->update_source
4214 && !peer->update_if)
4215 return 0;
4216
4217 if (peer->update_source) {
4218 sockunion_free(peer->update_source);
4219 peer->update_source = NULL;
4220 }
4221 if (peer->update_if) {
4222 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4223 peer->update_if = NULL;
4224 }
4225
4226 if (peer_group_active(peer)) {
4227 group = peer->group;
4228
4229 if (group->conf->update_source) {
4230 su = sockunion_dup(group->conf->update_source);
4231 peer->update_source = su;
4232 } else if (group->conf->update_if)
4233 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE,
4234 group->conf->update_if);
4235 }
4236
4237 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4238 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4239 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4240 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4241 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4242 } else
4243 bgp_session_reset(peer);
4244 return 0;
4245 }
4246
4247 /* peer-group member updates. */
4248 group = peer->group;
4249 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4250 if (!peer->update_source && !peer->update_if)
4251 continue;
4252
4253 if (peer->update_source) {
4254 sockunion_free(peer->update_source);
4255 peer->update_source = NULL;
4256 }
4257
4258 if (peer->update_if) {
4259 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4260 peer->update_if = NULL;
4261 }
4262
4263 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4264 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4265 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4266 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4267 } else
4268 bgp_session_reset(peer);
4269 }
4270 return 0;
4271}
4272
4273int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
4274 const char *rmap)
4275{
4276 struct peer_group *group;
4277 struct listnode *node, *nnode;
4278
4279 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
4280 || (rmap && !peer->default_rmap[afi][safi].name)
4281 || (rmap
4282 && strcmp(rmap, peer->default_rmap[afi][safi].name) != 0)) {
4283 SET_FLAG(peer->af_flags[afi][safi],
4284 PEER_FLAG_DEFAULT_ORIGINATE);
4285
4286 if (rmap) {
4287 if (peer->default_rmap[afi][safi].name)
4288 XFREE(MTYPE_ROUTE_MAP_NAME,
4289 peer->default_rmap[afi][safi].name);
4290 peer->default_rmap[afi][safi].name =
4291 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4292 peer->default_rmap[afi][safi].map =
4293 route_map_lookup_by_name(rmap);
4294 }
4295 }
4296
4297 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4298 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4299 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4300 bgp_default_originate(peer, afi, safi, 0);
4301 bgp_announce_route(peer, afi, safi);
4302 }
4303 return 0;
4304 }
4305
4306 /* peer-group member updates. */
4307 group = peer->group;
4308 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4309 SET_FLAG(peer->af_flags[afi][safi],
4310 PEER_FLAG_DEFAULT_ORIGINATE);
4311
4312 if (rmap) {
4313 if (peer->default_rmap[afi][safi].name)
4314 XFREE(MTYPE_ROUTE_MAP_NAME,
4315 peer->default_rmap[afi][safi].name);
4316 peer->default_rmap[afi][safi].name =
4317 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4318 peer->default_rmap[afi][safi].map =
4319 route_map_lookup_by_name(rmap);
4320 }
4321
4322 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4323 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4324 bgp_default_originate(peer, afi, safi, 0);
4325 bgp_announce_route(peer, afi, safi);
4326 }
4327 }
4328 return 0;
4329}
4330
4331int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
4332{
4333 struct peer_group *group;
4334 struct listnode *node, *nnode;
4335
4336 if (CHECK_FLAG(peer->af_flags[afi][safi],
4337 PEER_FLAG_DEFAULT_ORIGINATE)) {
4338 UNSET_FLAG(peer->af_flags[afi][safi],
4339 PEER_FLAG_DEFAULT_ORIGINATE);
4340
4341 if (peer->default_rmap[afi][safi].name)
4342 XFREE(MTYPE_ROUTE_MAP_NAME,
4343 peer->default_rmap[afi][safi].name);
4344 peer->default_rmap[afi][safi].name = NULL;
4345 peer->default_rmap[afi][safi].map = NULL;
4346 }
4347
4348 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4349 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4350 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4351 bgp_default_originate(peer, afi, safi, 1);
4352 bgp_announce_route(peer, afi, safi);
4353 }
4354 return 0;
4355 }
4356
4357 /* peer-group member updates. */
4358 group = peer->group;
4359 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4360 UNSET_FLAG(peer->af_flags[afi][safi],
4361 PEER_FLAG_DEFAULT_ORIGINATE);
4362
4363 if (peer->default_rmap[afi][safi].name)
4364 XFREE(MTYPE_ROUTE_MAP_NAME,
4365 peer->default_rmap[afi][safi].name);
4366 peer->default_rmap[afi][safi].name = NULL;
4367 peer->default_rmap[afi][safi].map = NULL;
4368
4369 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4370 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4371 bgp_default_originate(peer, afi, safi, 1);
4372 bgp_announce_route(peer, afi, safi);
4373 }
4374 }
4375 return 0;
4376}
4377
4378int peer_port_set(struct peer *peer, u_int16_t port)
4379{
4380 peer->port = port;
4381 return 0;
4382}
4383
4384int peer_port_unset(struct peer *peer)
4385{
4386 peer->port = BGP_PORT_DEFAULT;
4387 return 0;
4388}
4389
4390/*
4391 * Helper function that is called after the name of the policy
4392 * being used by a peer has changed (AF specific). Automatically
4393 * initiates inbound or outbound processing as needed.
4394 */
4395static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
4396 int outbound)
4397{
4398 if (outbound) {
4399 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4400 if (peer->status == Established)
4401 bgp_announce_route(peer, afi, safi);
4402 } else {
4403 if (peer->status != Established)
4404 return;
4405
4406 if (CHECK_FLAG(peer->af_flags[afi][safi],
4407 PEER_FLAG_SOFT_RECONFIG))
4408 bgp_soft_reconfig_in(peer, afi, safi);
4409 else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4410 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4411 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0);
4412 }
4413}
4414
4415
4416/* neighbor weight. */
4417int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight)
4418{
4419 struct peer_group *group;
4420 struct listnode *node, *nnode;
4421
4422 if (peer->weight[afi][safi] != weight) {
4423 peer->weight[afi][safi] = weight;
4424 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4425 peer_on_policy_change(peer, afi, safi, 0);
4426 }
4427
4428 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4429 return 0;
4430
4431 /* peer-group member updates. */
4432 group = peer->group;
4433 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4434 if (peer->weight[afi][safi] != weight) {
4435 peer->weight[afi][safi] = weight;
4436 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4437 peer_on_policy_change(peer, afi, safi, 0);
4438 }
4439 }
4440 return 0;
4441}
4442
4443int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
4444{
4445 struct peer_group *group;
4446 struct listnode *node, *nnode;
4447
4448 /* not the peer-group itself but a peer in a peer-group */
4449 if (peer_group_active(peer)) {
4450 group = peer->group;
4451
4452 /* inherit weight from the peer-group */
4453 if (CHECK_FLAG(group->conf->af_flags[afi][safi],
4454 PEER_FLAG_WEIGHT)) {
4455 peer->weight[afi][safi] =
4456 group->conf->weight[afi][safi];
4457 peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
4458 peer_on_policy_change(peer, afi, safi, 0);
4459 } else {
4460 if (CHECK_FLAG(peer->af_flags[afi][safi],
4461 PEER_FLAG_WEIGHT)) {
4462 peer->weight[afi][safi] = 0;
4463 peer_af_flag_unset(peer, afi, safi,
4464 PEER_FLAG_WEIGHT);
4465 peer_on_policy_change(peer, afi, safi, 0);
4466 }
4467 }
4468 }
4469
4470 else {
4471 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) {
4472 peer->weight[afi][safi] = 0;
4473 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
4474 peer_on_policy_change(peer, afi, safi, 0);
4475 }
4476
4477 /* peer-group member updates. */
4478 group = peer->group;
4479
4480 if (group) {
4481 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4482 peer)) {
4483 if (CHECK_FLAG(peer->af_flags[afi][safi],
4484 PEER_FLAG_WEIGHT)) {
4485 peer->weight[afi][safi] = 0;
4486 peer_af_flag_unset(peer, afi, safi,
4487 PEER_FLAG_WEIGHT);
4488 peer_on_policy_change(peer, afi, safi,
4489 0);
4490 }
4491 }
4492 }
4493 }
4494 return 0;
4495}
4496
4497int peer_timers_set(struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
4498{
4499 struct peer_group *group;
4500 struct listnode *node, *nnode;
4501
4502 /* keepalive value check. */
4503 if (keepalive > 65535)
4504 return BGP_ERR_INVALID_VALUE;
4505
4506 /* Holdtime value check. */
4507 if (holdtime > 65535)
4508 return BGP_ERR_INVALID_VALUE;
4509
4510 /* Holdtime value must be either 0 or greater than 3. */
4511 if (holdtime < 3 && holdtime != 0)
4512 return BGP_ERR_INVALID_VALUE;
4513
4514 /* Set value to the configuration. */
4515 SET_FLAG(peer->config, PEER_CONFIG_TIMER);
4516 peer->holdtime = holdtime;
4517 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4518
4519 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4520 return 0;
4521
4522 /* peer-group member updates. */
4523 group = peer->group;
4524 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4525 SET_FLAG(peer->config, PEER_CONFIG_TIMER);
4526 peer->holdtime = group->conf->holdtime;
4527 peer->keepalive = group->conf->keepalive;
4528 }
4529 return 0;
4530}
4531
4532int peer_timers_unset(struct peer *peer)
4533{
4534 struct peer_group *group;
4535 struct listnode *node, *nnode;
4536
4537 /* Clear configuration. */
4538 UNSET_FLAG(peer->config, PEER_CONFIG_TIMER);
4539 peer->keepalive = 0;
4540 peer->holdtime = 0;
4541
4542 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4543 return 0;
4544
4545 /* peer-group member updates. */
4546 group = peer->group;
4547 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4548 UNSET_FLAG(peer->config, PEER_CONFIG_TIMER);
4549 peer->holdtime = 0;
4550 peer->keepalive = 0;
4551 }
4552
4553 return 0;
4554}
4555
4556int peer_timers_connect_set(struct peer *peer, u_int32_t connect)
4557{
4558 struct peer_group *group;
4559 struct listnode *node, *nnode;
4560
4561 if (connect > 65535)
4562 return BGP_ERR_INVALID_VALUE;
4563
4564 /* Set value to the configuration. */
4565 SET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4566 peer->connect = connect;
4567
4568 /* Set value to timer setting. */
4569 peer->v_connect = connect;
4570
4571 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4572 return 0;
4573
4574 /* peer-group member updates. */
4575 group = peer->group;
4576 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4577 SET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4578 peer->connect = connect;
4579 peer->v_connect = connect;
4580 }
4581 return 0;
4582}
4583
4584int peer_timers_connect_unset(struct peer *peer)
4585{
4586 struct peer_group *group;
4587 struct listnode *node, *nnode;
4588
4589 /* Clear configuration. */
4590 UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4591 peer->connect = 0;
4592
4593 /* Set timer setting to default value. */
4594 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4595
4596 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4597 return 0;
4598
4599 /* peer-group member updates. */
4600 group = peer->group;
4601 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4602 UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4603 peer->connect = 0;
4604 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4605 }
4606 return 0;
4607}
4608
4609int peer_advertise_interval_set(struct peer *peer, u_int32_t routeadv)
4610{
4611 struct peer_group *group;
4612 struct listnode *node, *nnode;
4613
4614 if (routeadv > 600)
4615 return BGP_ERR_INVALID_VALUE;
4616
4617 SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4618 peer->routeadv = routeadv;
4619 peer->v_routeadv = routeadv;
4620
4621 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4622 update_group_adjust_peer_afs(peer);
4623 if (peer->status == Established)
4624 bgp_announce_route_all(peer);
4625 return 0;
4626 }
4627
4628 /* peer-group member updates. */
4629 group = peer->group;
4630 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4631 SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4632 peer->routeadv = routeadv;
4633 peer->v_routeadv = routeadv;
4634 update_group_adjust_peer_afs(peer);
4635 if (peer->status == Established)
4636 bgp_announce_route_all(peer);
4637 }
4638
4639 return 0;
4640}
4641
4642int peer_advertise_interval_unset(struct peer *peer)
4643{
4644 struct peer_group *group;
4645 struct listnode *node, *nnode;
4646
4647 UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4648 peer->routeadv = 0;
4649
4650 if (peer->sort == BGP_PEER_IBGP)
4651 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4652 else
4653 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
4654
4655 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4656 update_group_adjust_peer_afs(peer);
4657 if (peer->status == Established)
4658 bgp_announce_route_all(peer);
4659 return 0;
4660 }
4661
4662 /* peer-group member updates. */
4663 group = peer->group;
4664 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4665 UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4666 peer->routeadv = 0;
4667
4668 if (peer->sort == BGP_PEER_IBGP)
4669 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4670 else
4671 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
4672
4673 update_group_adjust_peer_afs(peer);
4674 if (peer->status == Established)
4675 bgp_announce_route_all(peer);
4676 }
4677
4678 return 0;
4679}
4680
4681/* neighbor interface */
4682void peer_interface_set(struct peer *peer, const char *str)
4683{
4684 if (peer->ifname)
4685 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4686 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
4687}
4688
4689void peer_interface_unset(struct peer *peer)
4690{
4691 if (peer->ifname)
4692 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4693 peer->ifname = NULL;
4694}
4695
4696/* Allow-as in. */
4697int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
4698 int allow_num, int origin)
4699{
4700 struct peer_group *group;
4701 struct listnode *node, *nnode;
4702
4703 if (origin) {
4704 if (peer->allowas_in[afi][safi]
4705 || CHECK_FLAG(peer->af_flags[afi][safi],
4706 PEER_FLAG_ALLOWAS_IN)
4707 || !CHECK_FLAG(peer->af_flags[afi][safi],
4708 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4709 peer->allowas_in[afi][safi] = 0;
4710 peer_af_flag_unset(peer, afi, safi,
4711 PEER_FLAG_ALLOWAS_IN);
4712 peer_af_flag_set(peer, afi, safi,
4713 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4714 peer_on_policy_change(peer, afi, safi, 0);
4715 }
4716
4717 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4718 return 0;
4719
4720 group = peer->group;
4721 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4722 if (peer->allowas_in[afi][safi]
4723 || CHECK_FLAG(peer->af_flags[afi][safi],
4724 PEER_FLAG_ALLOWAS_IN)
4725 || !CHECK_FLAG(peer->af_flags[afi][safi],
4726 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4727 peer->allowas_in[afi][safi] = 0;
4728 peer_af_flag_unset(peer, afi, safi,
4729 PEER_FLAG_ALLOWAS_IN);
4730 peer_af_flag_set(peer, afi, safi,
4731 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4732 peer_on_policy_change(peer, afi, safi, 0);
4733 }
4734 }
4735 } else {
4736 if (allow_num < 1 || allow_num > 10)
4737 return BGP_ERR_INVALID_VALUE;
4738
4739 if (peer->allowas_in[afi][safi] != allow_num
4740 || CHECK_FLAG(peer->af_flags[afi][safi],
4741 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4742 peer->allowas_in[afi][safi] = allow_num;
4743 peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4744 peer_af_flag_unset(peer, afi, safi,
4745 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4746 peer_on_policy_change(peer, afi, safi, 0);
4747 }
4748
4749 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4750 return 0;
4751
4752 group = peer->group;
4753 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4754 if (peer->allowas_in[afi][safi] != allow_num
4755 || CHECK_FLAG(peer->af_flags[afi][safi],
4756 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4757 peer->allowas_in[afi][safi] = allow_num;
4758 peer_af_flag_set(peer, afi, safi,
4759 PEER_FLAG_ALLOWAS_IN);
4760 peer_af_flag_unset(peer, afi, safi,
4761 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4762 peer_on_policy_change(peer, afi, safi, 0);
4763 }
4764 }
4765 }
4766
4767 return 0;
4768}
4769
4770int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
4771{
4772 struct peer_group *group;
4773 struct peer *tmp_peer;
4774 struct listnode *node, *nnode;
4775
4776 /* If this is a peer-group we must first clear the flags for all of the
4777 * peer-group members
4778 */
4779 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4780 group = peer->group;
4781 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
4782 if (CHECK_FLAG(tmp_peer->af_flags[afi][safi],
4783 PEER_FLAG_ALLOWAS_IN)
4784 || CHECK_FLAG(tmp_peer->af_flags[afi][safi],
4785 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4786 tmp_peer->allowas_in[afi][safi] = 0;
4787 peer_af_flag_unset(tmp_peer, afi, safi,
4788 PEER_FLAG_ALLOWAS_IN);
4789 peer_af_flag_unset(tmp_peer, afi, safi,
4790 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4791 peer_on_policy_change(tmp_peer, afi, safi, 0);
4792 }
4793 }
4794 }
4795
4796 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)
4797 || CHECK_FLAG(peer->af_flags[afi][safi],
4798 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4799 peer->allowas_in[afi][safi] = 0;
4800 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4801 peer_af_flag_unset(peer, afi, safi,
4802 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4803 peer_on_policy_change(peer, afi, safi, 0);
4804 }
4805
4806 return 0;
4807}
4808
4809int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
4810 int replace_as)
4811{
4812 struct bgp *bgp = peer->bgp;
4813 struct peer_group *group;
4814 struct listnode *node, *nnode;
4815
4816 if (peer_sort(peer) != BGP_PEER_EBGP
4817 && peer_sort(peer) != BGP_PEER_INTERNAL)
4818 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4819
4820 if (bgp->as == as)
4821 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4822
4823 if (peer->as == as)
4824 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4825
4826 if (peer->change_local_as == as
4827 && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
4828 && no_prepend)
4829 || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
4830 && !no_prepend))
4831 && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
4832 && replace_as)
4833 || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
4834 && !replace_as)))
4835 return 0;
4836
4837 peer->change_local_as = as;
4838 if (no_prepend)
4839 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4840 else
4841 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4842
4843 if (replace_as)
4844 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4845 else
4846 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4847
4848 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4849 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4850 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4851 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4852 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4853 } else
4854 bgp_session_reset(peer);
4855 return 0;
4856 }
4857
4858 group = peer->group;
4859 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4860 peer->change_local_as = as;
4861 if (no_prepend)
4862 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4863 else
4864 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4865
4866 if (replace_as)
4867 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4868 else
4869 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4870
4871 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4872 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4873 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4874 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4875 } else
4876 BGP_EVENT_ADD(peer, BGP_Stop);
4877 }
4878
4879 return 0;
4880}
4881
4882int peer_local_as_unset(struct peer *peer)
4883{
4884 struct peer_group *group;
4885 struct listnode *node, *nnode;
4886
4887 if (!peer->change_local_as)
4888 return 0;
4889
4890 peer->change_local_as = 0;
4891 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4892 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4893
4894 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4895 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4896 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4897 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4898 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4899 } else
4900 BGP_EVENT_ADD(peer, BGP_Stop);
4901
4902 return 0;
4903 }
4904
4905 group = peer->group;
4906 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4907 peer->change_local_as = 0;
4908 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4909 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4910
4911 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4912 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4913 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4914 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4915 } else
4916 bgp_session_reset(peer);
4917 }
4918 return 0;
4919}
4920
4921/* Set password for authenticating with the peer. */
4922int peer_password_set(struct peer *peer, const char *password)
4923{
4924 struct listnode *nn, *nnode;
4925 int len = password ? strlen(password) : 0;
4926 int ret = BGP_SUCCESS;
4927
4928 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
4929 return BGP_ERR_INVALID_VALUE;
4930
4931 if (peer->password && strcmp(peer->password, password) == 0
4932 && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4933 return 0;
4934
4935 if (peer->password)
4936 XFREE(MTYPE_PEER_PASSWORD, peer->password);
4937
4938 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4939
4940 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4941 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4942 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4943 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4944 else
4945 bgp_session_reset(peer);
4946
4947 if (BGP_PEER_SU_UNSPEC(peer))
4948 return BGP_SUCCESS;
4949
4950 return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS
4951 : BGP_ERR_TCPSIG_FAILED;
4952 }
4953
4954 for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) {
4955 if (peer->password && strcmp(peer->password, password) == 0)
4956 continue;
4957
4958 if (peer->password)
4959 XFREE(MTYPE_PEER_PASSWORD, peer->password);
4960
4961 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4962
4963 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4964 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4965 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4966 else
4967 bgp_session_reset(peer);
4968
4969 if (!BGP_PEER_SU_UNSPEC(peer)) {
4970 if (bgp_md5_set(peer) < 0)
4971 ret = BGP_ERR_TCPSIG_FAILED;
4972 }
4973 }
4974
4975 return ret;
4976}
4977
4978int peer_password_unset(struct peer *peer)
4979{
4980 struct listnode *nn, *nnode;
4981
4982 if (!peer->password && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4983 return 0;
4984
4985 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4986 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4987 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4988 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4989 else
4990 bgp_session_reset(peer);
4991
4992 if (peer->password)
4993 XFREE(MTYPE_PEER_PASSWORD, peer->password);
4994
4995 peer->password = NULL;
4996
4997 if (!BGP_PEER_SU_UNSPEC(peer))
4998 bgp_md5_unset(peer);
4999
5000 return 0;
5001 }
5002
5003 XFREE(MTYPE_PEER_PASSWORD, peer->password);
5004 peer->password = NULL;
5005
5006 for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) {
5007 if (!peer->password)
5008 continue;
5009
5010 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5011 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5012 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5013 else
5014 bgp_session_reset(peer);
5015
5016 XFREE(MTYPE_PEER_PASSWORD, peer->password);
5017 peer->password = NULL;
5018
5019 if (!BGP_PEER_SU_UNSPEC(peer))
5020 bgp_md5_unset(peer);
5021 }
5022
5023 return 0;
5024}
6b0655a2 5025
3f9c7369 5026
718e3744 5027/* Set distribute list to the peer. */
d62a17ae 5028int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5029 const char *name)
5030{
5031 struct bgp_filter *filter;
5032 struct peer_group *group;
5033 struct listnode *node, *nnode;
5034
5035 if (direct != FILTER_IN && direct != FILTER_OUT)
5036 return BGP_ERR_INVALID_VALUE;
5037
5038 filter = &peer->filter[afi][safi];
5039
5040 if (filter->plist[direct].name)
5041 return BGP_ERR_PEER_FILTER_CONFLICT;
5042
5043 if (filter->dlist[direct].name)
5044 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5045 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5046 filter->dlist[direct].alist = access_list_lookup(afi, name);
5047
5048 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5049 peer_on_policy_change(peer, afi, safi,
5050 (direct == FILTER_OUT) ? 1 : 0);
5051 return 0;
5052 }
5053
5054 group = peer->group;
5055 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5056 filter = &peer->filter[afi][safi];
5057
5058 if (filter->dlist[direct].name)
5059 XFREE(MTYPE_BGP_FILTER_NAME,
5060 filter->dlist[direct].name);
5061 filter->dlist[direct].name =
5062 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5063 filter->dlist[direct].alist = access_list_lookup(afi, name);
5064 peer_on_policy_change(peer, afi, safi,
5065 (direct == FILTER_OUT) ? 1 : 0);
5066 }
5067
5068 return 0;
5069}
5070
5071int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5072{
5073 struct bgp_filter *filter;
5074 struct bgp_filter *gfilter;
5075 struct peer_group *group;
5076 struct listnode *node, *nnode;
5077
5078 if (direct != FILTER_IN && direct != FILTER_OUT)
5079 return BGP_ERR_INVALID_VALUE;
5080
5081 filter = &peer->filter[afi][safi];
5082
5083 /* apply peer-group filter */
5084 if (peer_group_active(peer)) {
5085 gfilter = &peer->group->conf->filter[afi][safi];
5086
5087 if (gfilter->dlist[direct].name) {
5088 if (filter->dlist[direct].name)
5089 XFREE(MTYPE_BGP_FILTER_NAME,
5090 filter->dlist[direct].name);
5091 filter->dlist[direct].name =
5092 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5093 gfilter->dlist[direct].name);
5094 filter->dlist[direct].alist =
5095 gfilter->dlist[direct].alist;
5096 peer_on_policy_change(peer, afi, safi,
5097 (direct == FILTER_OUT) ? 1 : 0);
5098 return 0;
5099 }
5100 }
5101
5102 if (filter->dlist[direct].name)
5103 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5104 filter->dlist[direct].name = NULL;
5105 filter->dlist[direct].alist = NULL;
5106
5107 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5108 peer_on_policy_change(peer, afi, safi,
5109 (direct == FILTER_OUT) ? 1 : 0);
5110 return 0;
5111 }
5112
5113 group = peer->group;
5114 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5115 filter = &peer->filter[afi][safi];
5116
5117 if (filter->dlist[direct].name)
5118 XFREE(MTYPE_BGP_FILTER_NAME,
5119 filter->dlist[direct].name);
5120 filter->dlist[direct].name = NULL;
5121 filter->dlist[direct].alist = NULL;
5122 peer_on_policy_change(peer, afi, safi,
5123 (direct == FILTER_OUT) ? 1 : 0);
5124 }
5125
5126 return 0;
5127}
5128
5129/* Update distribute list. */
5130static void peer_distribute_update(struct access_list *access)
5131{
5132 afi_t afi;
5133 safi_t safi;
5134 int direct;
5135 struct listnode *mnode, *mnnode;
5136 struct listnode *node, *nnode;
5137 struct bgp *bgp;
5138 struct peer *peer;
5139 struct peer_group *group;
5140 struct bgp_filter *filter;
5141
5142 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5143 if (access->name)
5144 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
5145 access->name, 0, 0);
5146 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
5147 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5148 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5149 safi++) {
5150 filter = &peer->filter[afi][safi];
5151
5152 for (direct = FILTER_IN;
5153 direct < FILTER_MAX; direct++) {
5154 if (filter->dlist[direct].name)
5155 filter->dlist[direct]
5156 .alist = access_list_lookup(
5157 afi,
5158 filter->dlist[direct]
5159 .name);
5160 else
5161 filter->dlist[direct]
5162 .alist = NULL;
5163 }
5164 }
5165 }
5166 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
5167 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5168 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5169 safi++) {
5170 filter =
5171 &group->conf->filter[afi][safi];
5172
5173 for (direct = FILTER_IN;
5174 direct < FILTER_MAX; direct++) {
5175 if (filter->dlist[direct].name)
5176 filter->dlist[direct]
5177 .alist = access_list_lookup(
5178 afi,
5179 filter->dlist[direct]
5180 .name);
5181 else
5182 filter->dlist[direct]
5183 .alist = NULL;
5184 }
5185 }
5186 }
5187#if ENABLE_BGP_VNC
5188 vnc_prefix_list_update(bgp);
5189#endif
5190 }
5191}
5192
5193/* Set prefix list to the peer. */
5194int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5195 const char *name)
5196{
5197 struct bgp_filter *filter;
5198 struct peer_group *group;
5199 struct listnode *node, *nnode;
5200
5201 if (direct != FILTER_IN && direct != FILTER_OUT)
5202 return BGP_ERR_INVALID_VALUE;
5203
5204 filter = &peer->filter[afi][safi];
5205
5206 if (filter->dlist[direct].name)
5207 return BGP_ERR_PEER_FILTER_CONFLICT;
5208
5209 if (filter->plist[direct].name)
5210 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5211 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5212 filter->plist[direct].plist = prefix_list_lookup(afi, name);
5213
5214 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5215 peer_on_policy_change(peer, afi, safi,
5216 (direct == FILTER_OUT) ? 1 : 0);
5217 return 0;
5218 }
5219
5220 group = peer->group;
5221 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5222 filter = &peer->filter[afi][safi];
5223
5224 if (filter->plist[direct].name)
5225 XFREE(MTYPE_BGP_FILTER_NAME,
5226 filter->plist[direct].name);
5227 filter->plist[direct].name =
5228 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5229 filter->plist[direct].plist = prefix_list_lookup(afi, name);
5230 peer_on_policy_change(peer, afi, safi,
5231 (direct == FILTER_OUT) ? 1 : 0);
5232 }
5233 return 0;
5234}
5235
5236int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
5237 int direct)
5238{
5239 struct bgp_filter *filter;
5240 struct bgp_filter *gfilter;
5241 struct peer_group *group;
5242 struct listnode *node, *nnode;
5243
5244 if (direct != FILTER_IN && direct != FILTER_OUT)
5245 return BGP_ERR_INVALID_VALUE;
5246
5247 filter = &peer->filter[afi][safi];
5248
5249 /* apply peer-group filter */
5250 if (peer_group_active(peer)) {
5251 gfilter = &peer->group->conf->filter[afi][safi];
5252
5253 if (gfilter->plist[direct].name) {
5254 if (filter->plist[direct].name)
5255 XFREE(MTYPE_BGP_FILTER_NAME,
5256 filter->plist[direct].name);
5257 filter->plist[direct].name =
5258 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5259 gfilter->plist[direct].name);
5260 filter->plist[direct].plist =
5261 gfilter->plist[direct].plist;
5262 peer_on_policy_change(peer, afi, safi,
5263 (direct == FILTER_OUT) ? 1 : 0);
5264 return 0;
5265 }
5266 }
5267
5268 if (filter->plist[direct].name)
5269 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5270 filter->plist[direct].name = NULL;
5271 filter->plist[direct].plist = NULL;
5272
5273 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5274 peer_on_policy_change(peer, afi, safi,
5275 (direct == FILTER_OUT) ? 1 : 0);
5276 return 0;
5277 }
5278
5279 group = peer->group;
5280 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5281 filter = &peer->filter[afi][safi];
5282
5283 if (filter->plist[direct].name)
5284 XFREE(MTYPE_BGP_FILTER_NAME,
5285 filter->plist[direct].name);
5286 filter->plist[direct].name = NULL;
5287 filter->plist[direct].plist = NULL;
5288 peer_on_policy_change(peer, afi, safi,
5289 (direct == FILTER_OUT) ? 1 : 0);
5290 }
5291
5292 return 0;
5293}
5294
5295/* Update prefix-list list. */
5296static void peer_prefix_list_update(struct prefix_list *plist)
5297{
5298 struct listnode *mnode, *mnnode;
5299 struct listnode *node, *nnode;
5300 struct bgp *bgp;
5301 struct peer *peer;
5302 struct peer_group *group;
5303 struct bgp_filter *filter;
5304 afi_t afi;
5305 safi_t safi;
5306 int direct;
5307
5308 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5309
5310 /*
5311 * Update the prefix-list on update groups.
5312 */
5313 update_group_policy_update(
5314 bgp, BGP_POLICY_PREFIX_LIST,
5315 plist ? prefix_list_name(plist) : NULL, 0, 0);
5316
5317 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
5318 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5319 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5320 safi++) {
5321 filter = &peer->filter[afi][safi];
5322
5323 for (direct = FILTER_IN;
5324 direct < FILTER_MAX; direct++) {
5325 if (filter->plist[direct].name)
5326 filter->plist[direct]
5327 .plist = prefix_list_lookup(
5328 afi,
5329 filter->plist[direct]
5330 .name);
5331 else
5332 filter->plist[direct]
5333 .plist = NULL;
5334 }
5335 }
5336 }
5337 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
5338 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5339 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5340 safi++) {
5341 filter =
5342 &group->conf->filter[afi][safi];
5343
5344 for (direct = FILTER_IN;
5345 direct < FILTER_MAX; direct++) {
5346 if (filter->plist[direct].name)
5347 filter->plist[direct]
5348 .plist = prefix_list_lookup(
5349 afi,
5350 filter->plist[direct]
5351 .name);
5352 else
5353 filter->plist[direct]
5354 .plist = NULL;
5355 }
5356 }
5357 }
5358 }
5359}
5360
5361int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5362 const char *name)
5363{
5364 struct bgp_filter *filter;
5365 struct peer_group *group;
5366 struct listnode *node, *nnode;
5367
5368 if (direct != FILTER_IN && direct != FILTER_OUT)
5369 return BGP_ERR_INVALID_VALUE;
5370
5371 filter = &peer->filter[afi][safi];
5372
5373 if (filter->aslist[direct].name)
5374 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5375 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5376 filter->aslist[direct].aslist = as_list_lookup(name);
5377
5378 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5379 peer_on_policy_change(peer, afi, safi,
5380 (direct == FILTER_OUT) ? 1 : 0);
5381 return 0;
5382 }
5383
5384 group = peer->group;
5385 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5386 filter = &peer->filter[afi][safi];
5387
5388 if (filter->aslist[direct].name)
5389 XFREE(MTYPE_BGP_FILTER_NAME,
5390 filter->aslist[direct].name);
5391 filter->aslist[direct].name =
5392 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5393 filter->aslist[direct].aslist = as_list_lookup(name);
5394 peer_on_policy_change(peer, afi, safi,
5395 (direct == FILTER_OUT) ? 1 : 0);
5396 }
5397 return 0;
5398}
5399
5400int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5401{
5402 struct bgp_filter *filter;
5403 struct bgp_filter *gfilter;
5404 struct peer_group *group;
5405 struct listnode *node, *nnode;
5406
5407 if (direct != FILTER_IN && direct != FILTER_OUT)
5408 return BGP_ERR_INVALID_VALUE;
5409
5410 filter = &peer->filter[afi][safi];
5411
5412 /* apply peer-group filter */
5413 if (peer_group_active(peer)) {
5414 gfilter = &peer->group->conf->filter[afi][safi];
5415
5416 if (gfilter->aslist[direct].name) {
5417 if (filter->aslist[direct].name)
5418 XFREE(MTYPE_BGP_FILTER_NAME,
5419 filter->aslist[direct].name);
5420 filter->aslist[direct].name =
5421 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5422 gfilter->aslist[direct].name);
5423 filter->aslist[direct].aslist =
5424 gfilter->aslist[direct].aslist;
5425 peer_on_policy_change(peer, afi, safi,
5426 (direct == FILTER_OUT) ? 1 : 0);
5427 return 0;
5428 }
5429 }
5430
5431 if (filter->aslist[direct].name)
5432 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5433 filter->aslist[direct].name = NULL;
5434 filter->aslist[direct].aslist = NULL;
5435
5436 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5437 peer_on_policy_change(peer, afi, safi,
5438 (direct == FILTER_OUT) ? 1 : 0);
5439 return 0;
5440 }
5441
5442 group = peer->group;
5443 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5444 filter = &peer->filter[afi][safi];
5445
5446 if (filter->aslist[direct].name)
5447 XFREE(MTYPE_BGP_FILTER_NAME,
5448 filter->aslist[direct].name);
5449 filter->aslist[direct].name = NULL;
5450 filter->aslist[direct].aslist = NULL;
5451 peer_on_policy_change(peer, afi, safi,
5452 (direct == FILTER_OUT) ? 1 : 0);
5453 }
5454
5455 return 0;
5456}
5457
5458static void peer_aslist_update(const char *aslist_name)
5459{
5460 afi_t afi;
5461 safi_t safi;
5462 int direct;
5463 struct listnode *mnode, *mnnode;
5464 struct listnode *node, *nnode;
5465 struct bgp *bgp;
5466 struct peer *peer;
5467 struct peer_group *group;
5468 struct bgp_filter *filter;
5469
5470 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5471 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
5472 aslist_name, 0, 0);
5473
5474 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
5475 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5476 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5477 safi++) {
5478 filter = &peer->filter[afi][safi];
5479
5480 for (direct = FILTER_IN;
5481 direct < FILTER_MAX; direct++) {
5482 if (filter->aslist[direct].name)
5483 filter->aslist[direct]
5484 .aslist = as_list_lookup(
5485 filter->aslist[direct]
5486 .name);
5487 else
5488 filter->aslist[direct]
5489 .aslist = NULL;
5490 }
5491 }
5492 }
5493 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
5494 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5495 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5496 safi++) {
5497 filter =
5498 &group->conf->filter[afi][safi];
5499
5500 for (direct = FILTER_IN;
5501 direct < FILTER_MAX; direct++) {
5502 if (filter->aslist[direct].name)
5503 filter->aslist[direct]
5504 .aslist = as_list_lookup(
5505 filter->aslist[direct]
5506 .name);
5507 else
5508 filter->aslist[direct]
5509 .aslist = NULL;
5510 }
5511 }
5512 }
5513 }
5514}
5515
5516static void peer_aslist_add(char *aslist_name)
5517{
5518 peer_aslist_update(aslist_name);
5519 route_map_notify_dependencies((char *)aslist_name,
5520 RMAP_EVENT_ASLIST_ADDED);
5521}
5522
5523static void peer_aslist_del(const char *aslist_name)
5524{
5525 peer_aslist_update(aslist_name);
5526 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
5527}
5528
5529
5530int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5531 const char *name)
5532{
5533 struct bgp_filter *filter;
5534 struct peer_group *group;
5535 struct listnode *node, *nnode;
5536
5537 if (direct != RMAP_IN && direct != RMAP_OUT)
5538 return BGP_ERR_INVALID_VALUE;
5539
5540 filter = &peer->filter[afi][safi];
5541
5542 if (filter->map[direct].name)
5543 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5544
5545 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5546 filter->map[direct].map = route_map_lookup_by_name(name);
5547
5548 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5549 peer_on_policy_change(peer, afi, safi,
5550 (direct == RMAP_OUT) ? 1 : 0);
5551 return 0;
5552 }
5553
5554 group = peer->group;
5555 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5556 filter = &peer->filter[afi][safi];
5557
5558 if (filter->map[direct].name)
5559 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5560 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5561 filter->map[direct].map = route_map_lookup_by_name(name);
5562 peer_on_policy_change(peer, afi, safi,
5563 (direct == RMAP_OUT) ? 1 : 0);
5564 }
5565 return 0;
5566}
5567
5568/* Unset route-map from the peer. */
5569int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5570{
5571 struct bgp_filter *filter;
5572 struct bgp_filter *gfilter;
5573 struct peer_group *group;
5574 struct listnode *node, *nnode;
5575
5576 if (direct != RMAP_IN && direct != RMAP_OUT)
5577 return BGP_ERR_INVALID_VALUE;
5578
5579 filter = &peer->filter[afi][safi];
5580
5581 /* apply peer-group filter */
5582 if (peer_group_active(peer)) {
5583 gfilter = &peer->group->conf->filter[afi][safi];
5584
5585 if (gfilter->map[direct].name) {
5586 if (filter->map[direct].name)
5587 XFREE(MTYPE_BGP_FILTER_NAME,
5588 filter->map[direct].name);
5589 filter->map[direct].name =
5590 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5591 gfilter->map[direct].name);
5592 filter->map[direct].map = gfilter->map[direct].map;
5593 peer_on_policy_change(peer, afi, safi,
5594 (direct == RMAP_OUT) ? 1 : 0);
5595 return 0;
5596 }
5597 }
5598
5599 if (filter->map[direct].name)
5600 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5601 filter->map[direct].name = NULL;
5602 filter->map[direct].map = NULL;
5603
5604 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5605 peer_on_policy_change(peer, afi, safi,
5606 (direct == RMAP_OUT) ? 1 : 0);
5607 return 0;
5608 }
5609
5610 group = peer->group;
5611 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5612 filter = &peer->filter[afi][safi];
5613
5614 if (filter->map[direct].name)
5615 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5616 filter->map[direct].name = NULL;
5617 filter->map[direct].map = NULL;
5618 peer_on_policy_change(peer, afi, safi,
5619 (direct == RMAP_OUT) ? 1 : 0);
5620 }
5621 return 0;
5622}
5623
5624/* Set unsuppress-map to the peer. */
5625int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
5626 const char *name)
5627{
5628 struct bgp_filter *filter;
5629 struct peer_group *group;
5630 struct listnode *node, *nnode;
5631
5632 filter = &peer->filter[afi][safi];
5633
5634 if (filter->usmap.name)
5635 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5636
5637 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5638 filter->usmap.map = route_map_lookup_by_name(name);
5639
5640 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5641 peer_on_policy_change(peer, afi, safi, 1);
5642 return 0;
5643 }
5644
5645 group = peer->group;
5646 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5647 filter = &peer->filter[afi][safi];
5648
5649 if (filter->usmap.name)
5650 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5651 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5652 filter->usmap.map = route_map_lookup_by_name(name);
5653 peer_on_policy_change(peer, afi, safi, 1);
5654 }
5655 return 0;
5656}
5657
5658/* Unset route-map from the peer. */
5659int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5660{
d62a17ae 5661 struct bgp_filter *filter;
5662 struct peer_group *group;
5663 struct listnode *node, *nnode;
5664
5665 filter = &peer->filter[afi][safi];
718e3744 5666
d62a17ae 5667 if (filter->usmap.name)
5668 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5669 filter->usmap.name = NULL;
5670 filter->usmap.map = NULL;
718e3744 5671
d62a17ae 5672 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5673 peer_on_policy_change(peer, afi, safi, 1);
5674 return 0;
5675 }
718e3744 5676
d62a17ae 5677 group = peer->group;
5678 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5679 filter = &peer->filter[afi][safi];
718e3744 5680
d62a17ae 5681 if (filter->usmap.name)
5682 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5683 filter->usmap.name = NULL;
5684 filter->usmap.map = NULL;
5685 peer_on_policy_change(peer, afi, safi, 1);
5686 }
5687 return 0;
5688}
718e3744 5689
d62a17ae 5690int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
5691 u_int32_t max, u_char threshold, int warning,
5692 u_int16_t restart)
5693{
5694 struct peer_group *group;
5695 struct listnode *node, *nnode;
5696
5697 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5698 peer->pmax[afi][safi] = max;
5699 peer->pmax_threshold[afi][safi] = threshold;
5700 peer->pmax_restart[afi][safi] = restart;
5701 if (warning)
5702 SET_FLAG(peer->af_flags[afi][safi],
5703 PEER_FLAG_MAX_PREFIX_WARNING);
5704 else
5705 UNSET_FLAG(peer->af_flags[afi][safi],
5706 PEER_FLAG_MAX_PREFIX_WARNING);
5707
5708 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5709 group = peer->group;
5710 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5711 SET_FLAG(peer->af_flags[afi][safi],
5712 PEER_FLAG_MAX_PREFIX);
5713 peer->pmax[afi][safi] = max;
5714 peer->pmax_threshold[afi][safi] = threshold;
5715 peer->pmax_restart[afi][safi] = restart;
5716 if (warning)
5717 SET_FLAG(peer->af_flags[afi][safi],
5718 PEER_FLAG_MAX_PREFIX_WARNING);
5719 else
5720 UNSET_FLAG(peer->af_flags[afi][safi],
5721 PEER_FLAG_MAX_PREFIX_WARNING);
5722
5723 if ((peer->status == Established)
5724 && (peer->afc[afi][safi]))
5725 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
5726 }
5727 } else {
5728 if ((peer->status == Established) && (peer->afc[afi][safi]))
5729 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
5730 }
718e3744 5731
d62a17ae 5732 return 0;
5733}
718e3744 5734
d62a17ae 5735int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
5736{
5737 struct peer_group *group;
5738 struct listnode *node, *nnode;
5739
5740 /* apply peer-group config */
5741 if (peer_group_active(peer)) {
5742 if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
5743 PEER_FLAG_MAX_PREFIX))
5744 SET_FLAG(peer->af_flags[afi][safi],
5745 PEER_FLAG_MAX_PREFIX);
5746 else
5747 UNSET_FLAG(peer->af_flags[afi][safi],
5748 PEER_FLAG_MAX_PREFIX);
5749
5750 if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
5751 PEER_FLAG_MAX_PREFIX_WARNING))
5752 SET_FLAG(peer->af_flags[afi][safi],
5753 PEER_FLAG_MAX_PREFIX_WARNING);
5754 else
5755 UNSET_FLAG(peer->af_flags[afi][safi],
5756 PEER_FLAG_MAX_PREFIX_WARNING);
5757
5758 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
5759 peer->pmax_threshold[afi][safi] =
5760 peer->group->conf->pmax_threshold[afi][safi];
5761 peer->pmax_restart[afi][safi] =
5762 peer->group->conf->pmax_restart[afi][safi];
5763 return 0;
5764 }
718e3744 5765
d62a17ae 5766 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5767 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5768 peer->pmax[afi][safi] = 0;
5769 peer->pmax_threshold[afi][safi] = 0;
5770 peer->pmax_restart[afi][safi] = 0;
5771
5772 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5773 return 0;
5774
5775 group = peer->group;
5776 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5777 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5778 UNSET_FLAG(peer->af_flags[afi][safi],
5779 PEER_FLAG_MAX_PREFIX_WARNING);
5780 peer->pmax[afi][safi] = 0;
5781 peer->pmax_threshold[afi][safi] = 0;
5782 peer->pmax_restart[afi][safi] = 0;
5783 }
5784 return 0;
718e3744 5785}
5786
d62a17ae 5787int is_ebgp_multihop_configured(struct peer *peer)
718e3744 5788{
d62a17ae 5789 struct peer_group *group;
5790 struct listnode *node, *nnode;
5791 struct peer *peer1;
718e3744 5792
d62a17ae 5793 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5794 group = peer->group;
5795 if ((peer_sort(peer) != BGP_PEER_IBGP)
5796 && (group->conf->ttl != 1))
5797 return 1;
718e3744 5798
d62a17ae 5799 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) {
5800 if ((peer_sort(peer1) != BGP_PEER_IBGP)
5801 && (peer1->ttl != 1))
5802 return 1;
5803 }
5804 } else {
5805 if ((peer_sort(peer) != BGP_PEER_IBGP) && (peer->ttl != 1))
5806 return 1;
5807 }
5808 return 0;
5809}
718e3744 5810
d62a17ae 5811/* Set # of hops between us and BGP peer. */
5812int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
5813{
5814 struct peer_group *group;
5815 struct listnode *node, *nnode;
5816 int ret;
5817
5818 zlog_debug("peer_ttl_security_hops_set: set gtsm_hops to %d for %s",
5819 gtsm_hops, peer->host);
5820
5821 /* We cannot configure ttl-security hops when ebgp-multihop is already
5822 set. For non peer-groups, the check is simple. For peer-groups,
5823 it's
5824 slightly messy, because we need to check both the peer-group
5825 structure
5826 and all peer-group members for any trace of ebgp-multihop
5827 configuration
5828 before actually applying the ttl-security rules. Cisco really made a
5829 mess of this configuration parameter, and OpenBGPD got it right.
5830 */
5831
5832 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) {
5833 if (is_ebgp_multihop_configured(peer))
5834 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
5835
5836 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5837 peer->gtsm_hops = gtsm_hops;
5838
5839 /* Calling ebgp multihop also resets the session.
5840 * On restart, NHT will get setup correctly as will the
5841 * min & max ttls on the socket. The return value is
5842 * irrelevant.
5843 */
5844 ret = peer_ebgp_multihop_set(peer, MAXTTL);
5845
5846 if (ret != 0)
5847 return ret;
5848 } else {
5849 group = peer->group;
5850 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
5851 peer)) {
5852 peer->gtsm_hops = group->conf->gtsm_hops;
5853
5854 /* Calling ebgp multihop also resets the
5855 * session.
5856 * On restart, NHT will get setup correctly as
5857 * will the
5858 * min & max ttls on the socket. The return
5859 * value is
5860 * irrelevant.
5861 */
5862 peer_ebgp_multihop_set(peer, MAXTTL);
5863 }
5864 }
5865 } else {
5866 /* Post the first gtsm setup or if its ibgp, maxttl setting
5867 * isn't
5868 * necessary, just set the minttl.
5869 */
5870 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5871 peer->gtsm_hops = gtsm_hops;
5872
5873 if (peer->fd >= 0)
5874 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
5875 MAXTTL + 1 - gtsm_hops);
5876 if ((peer->status < Established) && peer->doppelganger
5877 && (peer->doppelganger->fd >= 0))
5878 sockopt_minttl(peer->su.sa.sa_family,
5879 peer->doppelganger->fd,
5880 MAXTTL + 1 - gtsm_hops);
5881 } else {
5882 group = peer->group;
5883 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
5884 peer)) {
5885 peer->gtsm_hops = group->conf->gtsm_hops;
5886
5887 /* Change setting of existing peer
5888 * established then change value (may break
5889 * connectivity)
5890 * not established yet (teardown session and
5891 * restart)
5892 * no session then do nothing (will get
5893 * handled by next connection)
5894 */
5895 if (peer->fd >= 0 && peer->gtsm_hops != 0)
5896 sockopt_minttl(
5897 peer->su.sa.sa_family, peer->fd,
5898 MAXTTL + 1 - peer->gtsm_hops);
5899 if ((peer->status < Established)
5900 && peer->doppelganger
5901 && (peer->doppelganger->fd >= 0))
5902 sockopt_minttl(peer->su.sa.sa_family,
5903 peer->doppelganger->fd,
5904 MAXTTL + 1 - gtsm_hops);
5905 }
5906 }
5907 }
718e3744 5908
d62a17ae 5909 return 0;
718e3744 5910}
5911
d62a17ae 5912int peer_ttl_security_hops_unset(struct peer *peer)
5913{
5914 struct peer_group *group;
5915 struct listnode *node, *nnode;
5916 int ret = 0;
5917
5918 zlog_debug("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s",
5919 peer->host);
5920
5921 /* if a peer-group member, then reset to peer-group default rather than
5922 * 0 */
5923 if (peer_group_active(peer))
5924 peer->gtsm_hops = peer->group->conf->gtsm_hops;
5925 else
5926 peer->gtsm_hops = 0;
5927
5928 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5929 /* Invoking ebgp_multihop_set will set the TTL back to the
5930 * original
5931 * value as well as restting the NHT and such. The session is
5932 * reset.
5933 */
5934 if (peer->sort == BGP_PEER_EBGP)
5935 ret = peer_ebgp_multihop_unset(peer);
5936 else {
5937 if (peer->fd >= 0)
5938 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
5939 0);
5940
5941 if ((peer->status < Established) && peer->doppelganger
5942 && (peer->doppelganger->fd >= 0))
5943 sockopt_minttl(peer->su.sa.sa_family,
5944 peer->doppelganger->fd, 0);
5945 }
5946 } else {
5947 group = peer->group;
5948 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5949 peer->gtsm_hops = 0;
5950 if (peer->sort == BGP_PEER_EBGP)
5951 ret = peer_ebgp_multihop_unset(peer);
5952 else {
5953 if (peer->fd >= 0)
5954 sockopt_minttl(peer->su.sa.sa_family,
5955 peer->fd, 0);
5956
5957 if ((peer->status < Established)
5958 && peer->doppelganger
5959 && (peer->doppelganger->fd >= 0))
5960 sockopt_minttl(peer->su.sa.sa_family,
5961 peer->doppelganger->fd,
5962 0);
5963 }
5964 }
5965 }
718e3744 5966
d62a17ae 5967 return ret;
5968}
5969
5970/*
5971 * If peer clear is invoked in a loop for all peers on the BGP instance,
5972 * it may end up freeing the doppelganger, and if this was the next node
5973 * to the current node, we would end up accessing the freed next node.
5974 * Pass along additional parameter which can be updated if next node
5975 * is freed; only required when walking the peer list on BGP instance.
5976 */
5977int peer_clear(struct peer *peer, struct listnode **nnode)
5978{
5979 if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
5980 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) {
5981 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
5982 if (peer->t_pmax_restart) {
5983 BGP_TIMER_OFF(peer->t_pmax_restart);
5984 if (bgp_debug_neighbor_events(peer))
5985 zlog_debug(
5986 "%s Maximum-prefix restart timer canceled",
5987 peer->host);
5988 }
5989 BGP_EVENT_ADD(peer, BGP_Start);
5990 return 0;
5991 }
5992
5993 peer->v_start = BGP_INIT_START_TIMER;
5994 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5995 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5996 BGP_NOTIFY_CEASE_ADMIN_RESET);
5997 else
5998 bgp_session_reset_safe(peer, nnode);
718e3744 5999 }
d62a17ae 6000 return 0;
718e3744 6001}
6b0655a2 6002
d62a17ae 6003int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
6004 enum bgp_clear_type stype)
718e3744 6005{
d62a17ae 6006 struct peer_af *paf;
718e3744 6007
d62a17ae 6008 if (peer->status != Established)
6009 return 0;
718e3744 6010
d62a17ae 6011 if (!peer->afc[afi][safi])
6012 return BGP_ERR_AF_UNCONFIGURED;
718e3744 6013
d62a17ae 6014 peer->rtt = sockopt_tcp_rtt(peer->fd);
718e3744 6015
d62a17ae 6016 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
6017 /* Clear the "neighbor x.x.x.x default-originate" flag */
6018 paf = peer_af_find(peer, afi, safi);
6019 if (paf && paf->subgroup
6020 && CHECK_FLAG(paf->subgroup->sflags,
6021 SUBGRP_STATUS_DEFAULT_ORIGINATE))
6022 UNSET_FLAG(paf->subgroup->sflags,
6023 SUBGRP_STATUS_DEFAULT_ORIGINATE);
718e3744 6024
d62a17ae 6025 bgp_announce_route(peer, afi, safi);
6026 }
718e3744 6027
d62a17ae 6028 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6029 if (CHECK_FLAG(peer->af_cap[afi][safi],
6030 PEER_CAP_ORF_PREFIX_SM_ADV)
6031 && (CHECK_FLAG(peer->af_cap[afi][safi],
6032 PEER_CAP_ORF_PREFIX_RM_RCV)
6033 || CHECK_FLAG(peer->af_cap[afi][safi],
6034 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
6035 struct bgp_filter *filter = &peer->filter[afi][safi];
6036 u_char prefix_type;
6037
6038 if (CHECK_FLAG(peer->af_cap[afi][safi],
6039 PEER_CAP_ORF_PREFIX_RM_RCV))
6040 prefix_type = ORF_TYPE_PREFIX;
6041 else
6042 prefix_type = ORF_TYPE_PREFIX_OLD;
6043
6044 if (filter->plist[FILTER_IN].plist) {
6045 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6046 PEER_STATUS_ORF_PREFIX_SEND))
6047 bgp_route_refresh_send(
6048 peer, afi, safi, prefix_type,
6049 REFRESH_DEFER, 1);
6050 bgp_route_refresh_send(peer, afi, safi,
6051 prefix_type,
6052 REFRESH_IMMEDIATE, 0);
6053 } else {
6054 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6055 PEER_STATUS_ORF_PREFIX_SEND))
6056 bgp_route_refresh_send(
6057 peer, afi, safi, prefix_type,
6058 REFRESH_IMMEDIATE, 1);
6059 else
6060 bgp_route_refresh_send(peer, afi, safi,
6061 0, 0, 0);
6062 }
6063 return 0;
6064 }
6065 }
718e3744 6066
d62a17ae 6067 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6068 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6069 /* If neighbor has soft reconfiguration inbound flag.
6070 Use Adj-RIB-In database. */
6071 if (CHECK_FLAG(peer->af_flags[afi][safi],
6072 PEER_FLAG_SOFT_RECONFIG))
6073 bgp_soft_reconfig_in(peer, afi, safi);
6074 else {
6075 /* If neighbor has route refresh capability, send route
6076 refresh
6077 message to the peer. */
6078 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6079 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6080 bgp_route_refresh_send(peer, afi, safi, 0, 0,
6081 0);
6082 else
6083 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6084 }
6085 }
6086 return 0;
718e3744 6087}
6088
d62a17ae 6089/* Display peer uptime.*/
6090char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
6091 json_object *json)
6092{
6093 time_t uptime1, epoch_tbuf;
6094 struct tm *tm;
6095
6096 /* Check buffer length. */
6097 if (len < BGP_UPTIME_LEN) {
6098 if (!use_json) {
6099 zlog_warn("peer_uptime (): buffer shortage %lu",
6100 (u_long)len);
6101 /* XXX: should return status instead of buf... */
6102 snprintf(buf, len, "<error> ");
6103 }
6104 return buf;
6105 }
6106
6107 /* If there is no connection has been done before print `never'. */
6108 if (uptime2 == 0) {
6109 if (use_json) {
6110 json_object_string_add(json, "peerUptime", "never");
6111 json_object_int_add(json, "peerUptimeMsec", 0);
6112 } else
6113 snprintf(buf, len, "never");
6114 return buf;
6115 }
718e3744 6116
d62a17ae 6117 /* Get current time. */
6118 uptime1 = bgp_clock();
6119 uptime1 -= uptime2;
6120 tm = gmtime(&uptime1);
718e3744 6121
d62a17ae 6122 if (uptime1 < ONE_DAY_SECOND)
6123 snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
6124 tm->tm_sec);
6125 else if (uptime1 < ONE_WEEK_SECOND)
6126 snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
6127 tm->tm_min);
6128 else if (uptime1 < ONE_YEAR_SECOND)
6129 snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7,
6130 tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
6131 else
6132 snprintf(buf, len, "%02dy%02dw%dd", tm->tm_year - 70,
6133 tm->tm_yday / 7,
6134 tm->tm_yday - ((tm->tm_yday / 7) * 7));
6135
6136 if (use_json) {
6137 epoch_tbuf = time(NULL) - uptime1;
6138 json_object_string_add(json, "peerUptime", buf);
6139 json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000);
6140 json_object_int_add(json, "peerUptimeEstablishedEpoch",
6141 epoch_tbuf);
6142 }
718e3744 6143
d62a17ae 6144 return buf;
718e3744 6145}
6146
2cb5980f
DL
6147#define afi_header_vty_out(vty, afi, safi, write, format, ...) \
6148 do { \
6149 bgp_config_write_family_header(vty, afi, safi, write); \
6150 vty_out(vty, format, ## __VA_ARGS__); \
6151 } while (0)
3f9c7369 6152
d62a17ae 6153static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
6154 afi_t afi, safi_t safi, int *write)
518f0eb1 6155{
d62a17ae 6156 struct bgp_filter *filter;
6157 struct bgp_filter *gfilter = NULL;
6158 char *addr;
6159 int in = FILTER_IN;
6160 int out = FILTER_OUT;
518f0eb1 6161
d62a17ae 6162 addr = peer->host;
6163 filter = &peer->filter[afi][safi];
518f0eb1 6164
d62a17ae 6165 if (peer_group_active(peer))
6166 gfilter = &peer->group->conf->filter[afi][safi];
6167
6168 /* distribute-list. */
6169 if (filter->dlist[in].name)
6170 if (!gfilter || !gfilter->dlist[in].name
6171 || strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
6172 != 0) {
6173 afi_header_vty_out(
6174 vty, afi, safi, write,
6175 " neighbor %s distribute-list %s in\n", addr,
6176 filter->dlist[in].name);
6177 }
6b0655a2 6178
d62a17ae 6179 if (filter->dlist[out].name && !gfilter) {
6180 afi_header_vty_out(vty, afi, safi, write,
6181 " neighbor %s distribute-list %s out\n",
6182 addr, filter->dlist[out].name);
6183 }
718e3744 6184
d62a17ae 6185 /* prefix-list. */
6186 if (filter->plist[in].name)
6187 if (!gfilter || !gfilter->plist[in].name
6188 || strcmp(filter->plist[in].name, gfilter->plist[in].name)
6189 != 0) {
6190 afi_header_vty_out(vty, afi, safi, write,
6191 " neighbor %s prefix-list %s in\n",
6192 addr, filter->plist[in].name);
6193 }
718e3744 6194
a1e91fee
BR
6195 if (filter->plist[out].name)
6196 if (!gfilter || !gfilter->plist[out].name
6197 || strcmp(filter->plist[out].name, gfilter->plist[out].name)
6198 != 0) {
6199 afi_header_vty_out(vty, afi, safi, write,
6200 " neighbor %s prefix-list %s out\n",
6201 addr, filter->plist[out].name);
6202 }
718e3744 6203
d62a17ae 6204 /* route-map. */
6205 if (filter->map[RMAP_IN].name)
6206 if (!gfilter || !gfilter->map[RMAP_IN].name
6207 || strcmp(filter->map[RMAP_IN].name,
6208 gfilter->map[RMAP_IN].name)
6209 != 0) {
6210 afi_header_vty_out(vty, afi, safi, write,
6211 " neighbor %s route-map %s in\n",
6212 addr, filter->map[RMAP_IN].name);
6213 }
518f0eb1 6214
d62a17ae 6215 if (filter->map[RMAP_OUT].name)
6216 if (!gfilter || !gfilter->map[RMAP_OUT].name
6217 || strcmp(filter->map[RMAP_OUT].name,
6218 gfilter->map[RMAP_OUT].name)
6219 != 0) {
6220 afi_header_vty_out(vty, afi, safi, write,
6221 " neighbor %s route-map %s out\n",
6222 addr, filter->map[RMAP_OUT].name);
6223 }
718e3744 6224
d62a17ae 6225 /* unsuppress-map */
6226 if (filter->usmap.name && !gfilter) {
6227 afi_header_vty_out(vty, afi, safi, write,
6228 " neighbor %s unsuppress-map %s\n", addr,
6229 filter->usmap.name);
6230 }
718e3744 6231
d62a17ae 6232 /* filter-list. */
6233 if (filter->aslist[in].name)
6234 if (!gfilter || !gfilter->aslist[in].name
6235 || strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
6236 != 0) {
6237 afi_header_vty_out(vty, afi, safi, write,
6238 " neighbor %s filter-list %s in\n",
6239 addr, filter->aslist[in].name);
6240 }
718e3744 6241
d62a17ae 6242 if (filter->aslist[out].name && !gfilter) {
6243 afi_header_vty_out(vty, afi, safi, write,
6244 " neighbor %s filter-list %s out\n", addr,
6245 filter->aslist[out].name);
6246 }
718e3744 6247}
6248
d62a17ae 6249/* BGP peer configuration display function. */
6250static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
6251 struct peer *peer)
6252{
6253 struct peer *g_peer = NULL;
6254 char buf[SU_ADDRSTRLEN];
6255 char *addr;
6256 int if_pg_printed = FALSE;
6257 int if_ras_printed = FALSE;
6258
6259 /* Skip dynamic neighbors. */
6260 if (peer_dynamic_neighbor(peer))
6261 return;
6262
6263 if (peer->conf_if)
6264 addr = peer->conf_if;
6265 else
6266 addr = peer->host;
6267
6268 /************************************
6269 ****** Global to the neighbor ******
6270 ************************************/
6271 if (peer->conf_if) {
6272 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
6273 vty_out(vty, " neighbor %s interface v6only", addr);
6274 else
6275 vty_out(vty, " neighbor %s interface", addr);
6276
6277 if (peer_group_active(peer)) {
6278 vty_out(vty, " peer-group %s", peer->group->name);
6279 if_pg_printed = TRUE;
6280 } else if (peer->as_type == AS_SPECIFIED) {
6281 vty_out(vty, " remote-as %u", peer->as);
6282 if_ras_printed = TRUE;
6283 } else if (peer->as_type == AS_INTERNAL) {
6284 vty_out(vty, " remote-as internal");
6285 if_ras_printed = TRUE;
6286 } else if (peer->as_type == AS_EXTERNAL) {
6287 vty_out(vty, " remote-as external");
6288 if_ras_printed = TRUE;
6289 }
718e3744 6290
d62a17ae 6291 vty_out(vty, "\n");
6292 }
718e3744 6293
d62a17ae 6294 /* remote-as and peer-group */
6295 /* peer is a member of a peer-group */
6296 if (peer_group_active(peer)) {
6297 g_peer = peer->group->conf;
6298
6299 if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) {
6300 if (peer->as_type == AS_SPECIFIED) {
6301 vty_out(vty, " neighbor %s remote-as %u\n",
6302 addr, peer->as);
6303 } else if (peer->as_type == AS_INTERNAL) {
6304 vty_out(vty,
6305 " neighbor %s remote-as internal\n",
6306 addr);
6307 } else if (peer->as_type == AS_EXTERNAL) {
6308 vty_out(vty,
6309 " neighbor %s remote-as external\n",
6310 addr);
6311 }
6312 }
718e3744 6313
d62a17ae 6314 /* For swpX peers we displayed the peer-group
6315 * via 'neighbor swpX interface peer-group WORD' */
6316 if (!if_pg_printed)
6317 vty_out(vty, " neighbor %s peer-group %s\n", addr,
6318 peer->group->name);
6319 }
718e3744 6320
d62a17ae 6321 /* peer is NOT a member of a peer-group */
6322 else {
6323 /* peer is a peer-group, declare the peer-group */
6324 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6325 vty_out(vty, " neighbor %s peer-group\n", addr);
6326 }
6b0655a2 6327
d62a17ae 6328 if (!if_ras_printed) {
6329 if (peer->as_type == AS_SPECIFIED) {
6330 vty_out(vty, " neighbor %s remote-as %u\n",
6331 addr, peer->as);
6332 } else if (peer->as_type == AS_INTERNAL) {
6333 vty_out(vty,
6334 " neighbor %s remote-as internal\n",
6335 addr);
6336 } else if (peer->as_type == AS_EXTERNAL) {
6337 vty_out(vty,
6338 " neighbor %s remote-as external\n",
6339 addr);
6340 }
6341 }
6342 }
718e3744 6343
d62a17ae 6344 /* local-as */
6345 if (peer->change_local_as) {
6346 if (!peer_group_active(peer)
6347 || peer->change_local_as != g_peer->change_local_as
6348 || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
6349 != CHECK_FLAG(g_peer->flags,
6350 PEER_FLAG_LOCAL_AS_NO_PREPEND))
6351 || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
6352 != CHECK_FLAG(g_peer->flags,
6353 PEER_FLAG_LOCAL_AS_REPLACE_AS))) {
6354 vty_out(vty, " neighbor %s local-as %u%s%s\n", addr,
6355 peer->change_local_as,
6356 CHECK_FLAG(peer->flags,
6357 PEER_FLAG_LOCAL_AS_NO_PREPEND)
6358 ? " no-prepend"
6359 : "",
6360 CHECK_FLAG(peer->flags,
6361 PEER_FLAG_LOCAL_AS_REPLACE_AS)
6362 ? " replace-as"
6363 : "");
6364 }
5f9adb5d 6365 }
5f9adb5d 6366
d62a17ae 6367 /* description */
6368 if (peer->desc) {
6369 vty_out(vty, " neighbor %s description %s\n", addr, peer->desc);
6370 }
fa411a21 6371
d62a17ae 6372 /* shutdown */
6373 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
6374 if (!peer_group_active(peer)
6375 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_SHUTDOWN)
6376 || peer->tx_shutdown_message) {
6377 if (peer->tx_shutdown_message)
6378 vty_out(vty,
6379 " neighbor %s shutdown message %s\n",
6380 addr, peer->tx_shutdown_message);
6381 else
6382 vty_out(vty, " neighbor %s shutdown\n", addr);
6383 }
6384 }
fa411a21 6385
d62a17ae 6386 /* bfd */
6387 if (peer->bfd_info) {
6388 if (!peer_group_active(peer) || !g_peer->bfd_info) {
6389 bgp_bfd_peer_config_write(vty, peer, addr);
6390 }
6391 }
e5cc509c 6392
d62a17ae 6393 /* password */
6394 if (peer->password) {
6395 if (!peer_group_active(peer) || !g_peer->password
6396 || strcmp(peer->password, g_peer->password) != 0) {
6397 vty_out(vty, " neighbor %s password %s\n", addr,
6398 peer->password);
6399 }
6400 }
fa411a21 6401
d62a17ae 6402 /* neighbor solo */
6403 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
6404 if (!peer_group_active(peer)) {
6405 vty_out(vty, " neighbor %s solo\n", addr);
6406 }
6407 }
fa411a21 6408
d62a17ae 6409 /* BGP port */
6410 if (peer->port != BGP_PORT_DEFAULT) {
6411 vty_out(vty, " neighbor %s port %d\n", addr, peer->port);
6412 }
e5cc509c 6413
d62a17ae 6414 /* Local interface name */
6415 if (peer->ifname) {
6416 vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname);
e5cc509c 6417 }
fa411a21 6418
d62a17ae 6419 /* passive */
6420 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
6421 if (!peer_group_active(peer)
6422 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_PASSIVE)) {
6423 vty_out(vty, " neighbor %s passive\n", addr);
6424 }
e5cc509c 6425 }
1ff9a340 6426
d62a17ae 6427 /* ebgp-multihop */
6428 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1
6429 && !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) {
6430 if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) {
6431 vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr,
6432 peer->ttl);
6433 }
fa411a21 6434 }
fa411a21 6435
d62a17ae 6436 /* ttl-security hops */
6437 if (peer->gtsm_hops != 0) {
6438 if (!peer_group_active(peer)
6439 || g_peer->gtsm_hops != peer->gtsm_hops) {
6440 vty_out(vty, " neighbor %s ttl-security hops %d\n",
6441 addr, peer->gtsm_hops);
6442 }
6443 }
6444
6445 /* disable-connected-check */
6446 if (CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
6447 if (!peer_group_active(peer)
6448 || !CHECK_FLAG(g_peer->flags,
6449 PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
6450 vty_out(vty, " neighbor %s disable-connected-check\n",
6451 addr);
6452 }
6453 }
6454
6455 /* update-source */
6456 if (peer->update_if) {
6457 if (!peer_group_active(peer) || !g_peer->update_if
6458 || strcmp(g_peer->update_if, peer->update_if) != 0) {
6459 vty_out(vty, " neighbor %s update-source %s\n", addr,
6460 peer->update_if);
6461 }
6462 }
6463 if (peer->update_source) {
6464 if (!peer_group_active(peer) || !g_peer->update_source
6465 || sockunion_cmp(g_peer->update_source, peer->update_source)
6466 != 0) {
6467 vty_out(vty, " neighbor %s update-source %s\n", addr,
6468 sockunion2str(peer->update_source, buf,
6469 SU_ADDRSTRLEN));
6470 }
6471 }
6472
6473 /* advertisement-interval */
6474 if (CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV)
6475 && ((!peer_group_active(peer)
6476 && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV)
6477 || (peer_group_active(peer)
6478 && peer->v_routeadv != g_peer->v_routeadv))) {
6479 vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
6480 peer->v_routeadv);
6481 }
6482
6483 /* timers */
6484 if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)
6485 && ((!peer_group_active(peer)
6486 && (peer->keepalive != BGP_DEFAULT_KEEPALIVE
6487 || peer->holdtime != BGP_DEFAULT_HOLDTIME))
6488 || (peer_group_active(peer)
6489 && (peer->keepalive != g_peer->keepalive
6490 || peer->holdtime != g_peer->holdtime)))) {
6491 vty_out(vty, " neighbor %s timers %u %u\n", addr,
6492 peer->keepalive, peer->holdtime);
6493 }
6494
6495 if (CHECK_FLAG(peer->config, PEER_CONFIG_CONNECT)
6496 && ((!peer_group_active(peer)
6497 && peer->connect != BGP_DEFAULT_CONNECT_RETRY)
6498 || (peer_group_active(peer)
6499 && peer->connect != g_peer->connect)))
6b0655a2 6500
718e3744 6501 {
d62a17ae 6502 vty_out(vty, " neighbor %s timers connect %u\n", addr,
6503 peer->connect);
718e3744 6504 }
6b0655a2 6505
d62a17ae 6506 /* capability dynamic */
6507 if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
6508 if (!peer_group_active(peer)
6509 || !CHECK_FLAG(g_peer->flags,
6510 PEER_FLAG_DYNAMIC_CAPABILITY)) {
6511 vty_out(vty, " neighbor %s capability dynamic\n", addr);
6512 }
6513 }
718e3744 6514
d62a17ae 6515 /* capability extended-nexthop */
6516 if (peer->ifp && !CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6517 if (!peer_group_active(peer)
6518 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6519 vty_out(vty,
6520 " no neighbor %s capability extended-nexthop\n",
6521 addr);
6522 }
6523 }
718e3744 6524
d62a17ae 6525 if (!peer->ifp && CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6526 if (!peer_group_active(peer)
6527 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6528 vty_out(vty,
6529 " neighbor %s capability extended-nexthop\n",
6530 addr);
6531 }
6532 }
6533
6534 /* dont-capability-negotiation */
6535 if (CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) {
6536 if (!peer_group_active(peer)
6537 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) {
6538 vty_out(vty, " neighbor %s dont-capability-negotiate\n",
6539 addr);
6540 }
6541 }
6542
6543 /* override-capability */
6544 if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) {
6545 if (!peer_group_active(peer)
6546 || !CHECK_FLAG(g_peer->flags,
6547 PEER_FLAG_OVERRIDE_CAPABILITY)) {
6548 vty_out(vty, " neighbor %s override-capability\n",
6549 addr);
6550 }
6551 }
6552
6553 /* strict-capability-match */
6554 if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
6555 if (!peer_group_active(peer)
6556 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
6557 vty_out(vty, " neighbor %s strict-capability-match\n",
6558 addr);
6559 }
6560 }
0b960b4d
DW
6561}
6562
0b960b4d 6563/* BGP peer configuration display function. */
d62a17ae 6564static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
6565 struct peer *peer, afi_t afi, safi_t safi,
6566 int *write)
6567{
6568 struct peer *g_peer = NULL;
6569 char *addr;
6570
6571 /* Skip dynamic neighbors. */
6572 if (peer_dynamic_neighbor(peer))
6573 return;
6574
6575 if (peer->conf_if)
6576 addr = peer->conf_if;
6577 else
6578 addr = peer->host;
6579
6580 /************************************
6581 ****** Per AF to the neighbor ******
6582 ************************************/
6583 if (peer_group_active(peer)) {
6584 g_peer = peer->group->conf;
6585
6586 /* If the peer-group is active but peer is not, print a 'no
6587 * activate' */
6588 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
6589 afi_header_vty_out(vty, afi, safi, write,
6590 " no neighbor %s activate\n", addr);
6591 }
6592
6593 /* If the peer-group is not active but peer is, print an
6594 'activate' */
6595 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
6596 afi_header_vty_out(vty, afi, safi, write,
6597 " neighbor %s activate\n", addr);
6598 }
6599 } else {
6600 if (peer->afc[afi][safi]) {
6601 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
6602 if (bgp_flag_check(bgp,
6603 BGP_FLAG_NO_DEFAULT_IPV4)) {
6604 afi_header_vty_out(
6605 vty, afi, safi, write,
6606 " neighbor %s activate\n",
6607 addr);
6608 }
6609 } else
6610 afi_header_vty_out(vty, afi, safi, write,
6611 " neighbor %s activate\n",
6612 addr);
6613 } else {
6614 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
6615 if (!bgp_flag_check(bgp,
6616 BGP_FLAG_NO_DEFAULT_IPV4)) {
6617 afi_header_vty_out(
6618 vty, afi, safi, write,
6619 " no neighbor %s activate\n",
6620 addr);
6621 }
6622 }
6623 }
6624 }
6625
6626 /* addpath TX knobs */
6627 if (peergroup_af_flag_check(peer, afi, safi,
6628 PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
6629 afi_header_vty_out(vty, afi, safi, write,
6630 " neighbor %s addpath-tx-all-paths\n",
6631 addr);
6632 }
6633
6634 if (peergroup_af_flag_check(peer, afi, safi,
6635 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
6636 afi_header_vty_out(vty, afi, safi, write,
6637 " neighbor %s addpath-tx-bestpath-per-AS\n",
6638 addr);
6639 }
6640
6641 /* ORF capability. */
6642 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
6643 || peergroup_af_flag_check(peer, afi, safi,
6644 PEER_FLAG_ORF_PREFIX_RM)) {
6645 afi_header_vty_out(vty, afi, safi, write,
6646 " neighbor %s capability orf prefix-list",
6647 addr);
6648
6649 if (peergroup_af_flag_check(peer, afi, safi,
6650 PEER_FLAG_ORF_PREFIX_SM)
6651 && peergroup_af_flag_check(peer, afi, safi,
6652 PEER_FLAG_ORF_PREFIX_RM))
6653 vty_out(vty, " both");
6654 else if (peergroup_af_flag_check(peer, afi, safi,
6655 PEER_FLAG_ORF_PREFIX_SM))
6656 vty_out(vty, " send");
6657 else
6658 vty_out(vty, " receive");
6659 vty_out(vty, "\n");
6660 }
6661
6662 /* Route reflector client. */
6663 if (peergroup_af_flag_check(peer, afi, safi,
6664 PEER_FLAG_REFLECTOR_CLIENT)) {
6665 afi_header_vty_out(vty, afi, safi, write,
6666 " neighbor %s route-reflector-client\n",
6667 addr);
6668 }
6669
6670 /* next-hop-self force */
6671 if (peergroup_af_flag_check(peer, afi, safi,
6672 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
6673 afi_header_vty_out(vty, afi, safi, write,
6674 " neighbor %s next-hop-self force\n", addr);
6675 }
6676
6677 /* next-hop-self */
6678 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
6679 afi_header_vty_out(vty, afi, safi, write,
6680 " neighbor %s next-hop-self\n", addr);
6681 }
6682
6683 /* remove-private-AS */
6684 if (peergroup_af_flag_check(peer, afi, safi,
6685 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
6686 afi_header_vty_out(
6687 vty, afi, safi, write,
6688 " neighbor %s remove-private-AS all replace-AS\n",
6689 addr);
6690 }
6691
6692 else if (peergroup_af_flag_check(peer, afi, safi,
6693 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
6694 afi_header_vty_out(
6695 vty, afi, safi, write,
6696 " neighbor %s remove-private-AS replace-AS\n", addr);
6697 }
6698
6699 else if (peergroup_af_flag_check(peer, afi, safi,
6700 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
6701 afi_header_vty_out(vty, afi, safi, write,
6702 " neighbor %s remove-private-AS all\n",
6703 addr);
6704 }
6705
6706 else if (peergroup_af_flag_check(peer, afi, safi,
6707 PEER_FLAG_REMOVE_PRIVATE_AS)) {
6708 afi_header_vty_out(vty, afi, safi, write,
6709 " neighbor %s remove-private-AS\n", addr);
6710 }
6711
6712 /* as-override */
6713 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
6714 afi_header_vty_out(vty, afi, safi, write,
6715 " neighbor %s as-override\n", addr);
6716 }
6717
6718 /* send-community print. */
6719 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
6720 if (peergroup_af_flag_check(peer, afi, safi,
6721 PEER_FLAG_SEND_COMMUNITY)
6722 && peergroup_af_flag_check(peer, afi, safi,
6723 PEER_FLAG_SEND_EXT_COMMUNITY)
6724 && peergroup_af_flag_check(
6725 peer, afi, safi,
6726 PEER_FLAG_SEND_LARGE_COMMUNITY)) {
6727 afi_header_vty_out(vty, afi, safi, write,
6728 " neighbor %s send-community all\n",
6729 addr);
6730 } else if (peergroup_af_flag_check(
6731 peer, afi, safi,
6732 PEER_FLAG_SEND_LARGE_COMMUNITY)) {
6733 afi_header_vty_out(
6734 vty, afi, safi, write,
6735 " neighbor %s send-community large\n", addr);
6736 } else if (peergroup_af_flag_check(
6737 peer, afi, safi,
6738 PEER_FLAG_SEND_EXT_COMMUNITY)) {
6739 afi_header_vty_out(
6740 vty, afi, safi, write,
6741 " neighbor %s send-community extended\n",
6742 addr);
6743 } else if (peergroup_af_flag_check(peer, afi, safi,
6744 PEER_FLAG_SEND_COMMUNITY)) {
6745 afi_header_vty_out(vty, afi, safi, write,
6746 " neighbor %s send-community\n",
6747 addr);
6748 }
6749 } else {
6750 if (!peer_af_flag_check(peer, afi, safi,
6751 PEER_FLAG_SEND_COMMUNITY)
9d303b37
DL
6752 && (!g_peer || peer_af_flag_check(g_peer, afi, safi,
6753 PEER_FLAG_SEND_COMMUNITY))
d62a17ae 6754 && !peer_af_flag_check(peer, afi, safi,
6755 PEER_FLAG_SEND_EXT_COMMUNITY)
6756 && (!g_peer
6757 || peer_af_flag_check(g_peer, afi, safi,
6758 PEER_FLAG_SEND_EXT_COMMUNITY))
6759 && !peer_af_flag_check(peer, afi, safi,
6760 PEER_FLAG_SEND_LARGE_COMMUNITY)
9d303b37
DL
6761 && (!g_peer || peer_af_flag_check(
6762 g_peer, afi, safi,
6763 PEER_FLAG_SEND_LARGE_COMMUNITY))) {
d62a17ae 6764 afi_header_vty_out(
6765 vty, afi, safi, write,
6766 " no neighbor %s send-community all\n", addr);
6767 } else {
6768 if (!peer_af_flag_check(peer, afi, safi,
6769 PEER_FLAG_SEND_LARGE_COMMUNITY)
6770 && (!g_peer
6771 || peer_af_flag_check(
6772 g_peer, afi, safi,
6773 PEER_FLAG_SEND_LARGE_COMMUNITY))) {
6774 afi_header_vty_out(
6775 vty, afi, safi, write,
6776 " no neighbor %s send-community large\n",
6777 addr);
6778 }
6779
6780 if (!peer_af_flag_check(peer, afi, safi,
6781 PEER_FLAG_SEND_EXT_COMMUNITY)
6782 && (!g_peer
6783 || peer_af_flag_check(
6784 g_peer, afi, safi,
6785 PEER_FLAG_SEND_EXT_COMMUNITY))) {
6786 afi_header_vty_out(
6787 vty, afi, safi, write,
6788 " no neighbor %s send-community extended\n",
6789 addr);
6790 }
6791
6792 if (!peer_af_flag_check(peer, afi, safi,
6793 PEER_FLAG_SEND_COMMUNITY)
9d303b37
DL
6794 && (!g_peer || peer_af_flag_check(
6795 g_peer, afi, safi,
6796 PEER_FLAG_SEND_COMMUNITY))) {
d62a17ae 6797 afi_header_vty_out(
6798 vty, afi, safi, write,
6799 " no neighbor %s send-community\n",
6800 addr);
6801 }
6802 }
6803 }
6804
6805 /* Default information */
6806 if (peergroup_af_flag_check(peer, afi, safi,
6807 PEER_FLAG_DEFAULT_ORIGINATE)
6808 || (g_peer
6809 && ((peer->default_rmap[afi][safi].name
6810 && !g_peer->default_rmap[afi][safi].name)
6811 || (!peer->default_rmap[afi][safi].name
6812 && g_peer->default_rmap[afi][safi].name)
6813 || (peer->default_rmap[afi][safi].name
6814 && strcmp(peer->default_rmap[afi][safi].name,
6815 g_peer->default_rmap[afi][safi].name))))) {
6816 afi_header_vty_out(vty, afi, safi, write,
6817 " neighbor %s default-originate", addr);
6818 if (peer->default_rmap[afi][safi].name)
6819 vty_out(vty, " route-map %s",
6820 peer->default_rmap[afi][safi].name);
6821 vty_out(vty, "\n");
6822 }
6823
6824 /* Soft reconfiguration inbound. */
6825 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
6826 afi_header_vty_out(
6827 vty, afi, safi, write,
6828 " neighbor %s soft-reconfiguration inbound\n", addr);
6829 }
6830
6831 /* maximum-prefix. */
6832 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
6833 if (!peer_group_active(peer)
6834 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
6835 || g_peer->pmax_threshold[afi][safi]
6836 != peer->pmax_threshold[afi][safi]
6837 || CHECK_FLAG(g_peer->af_flags[afi][safi],
6838 PEER_FLAG_MAX_PREFIX_WARNING)
6839 != CHECK_FLAG(peer->af_flags[afi][safi],
6840 PEER_FLAG_MAX_PREFIX_WARNING)) {
6841 afi_header_vty_out(vty, afi, safi, write,
6842 " neighbor %s maximum-prefix %lu",
6843 addr, peer->pmax[afi][safi]);
6844 if (peer->pmax_threshold[afi][safi]
6845 != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6846 vty_out(vty, " %u",
6847 peer->pmax_threshold[afi][safi]);
6848 if (CHECK_FLAG(peer->af_flags[afi][safi],
6849 PEER_FLAG_MAX_PREFIX_WARNING))
6850 vty_out(vty, " warning-only");
6851 if (peer->pmax_restart[afi][safi])
6852 vty_out(vty, " restart %u",
6853 peer->pmax_restart[afi][safi]);
6854 vty_out(vty, "\n");
6855 }
6856
6857 /* Route server client. */
6858 if (peergroup_af_flag_check(peer, afi, safi,
6859 PEER_FLAG_RSERVER_CLIENT)) {
6860 afi_header_vty_out(vty, afi, safi, write,
6861 " neighbor %s route-server-client\n", addr);
6862 }
6863
6864 /* Nexthop-local unchanged. */
6865 if (peergroup_af_flag_check(peer, afi, safi,
6866 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
6867 afi_header_vty_out(vty, afi, safi, write,
6868 " neighbor %s nexthop-local unchanged\n",
6869 addr);
6870 }
6871
6872 /* allowas-in <1-10> */
6873 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
6874 if (!peer_group_active(peer)
6875 || !peer_af_flag_check(g_peer, afi, safi,
6876 PEER_FLAG_ALLOWAS_IN)
6877 || peer->allowas_in[afi][safi]
6878 != g_peer->allowas_in[afi][safi]) {
6879 if (peer->allowas_in[afi][safi] == 3) {
6880 afi_header_vty_out(vty, afi, safi, write,
6881 " neighbor %s allowas-in\n",
6882 addr);
6883 } else {
6884 afi_header_vty_out(
6885 vty, afi, safi, write,
6886 " neighbor %s allowas-in %d\n", addr,
6887 peer->allowas_in[afi][safi]);
6888 }
6889 }
6890 }
6891
6892 /* allowas-in origin */
6893 else if (peer_af_flag_check(peer, afi, safi,
6894 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
6895 if (!peer_group_active(peer)
6896 || !peer_af_flag_check(g_peer, afi, safi,
6897 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
6898 afi_header_vty_out(vty, afi, safi, write,
6899 " neighbor %s allowas-in origin\n",
6900 addr);
6901 }
6902 }
6903
6904 /* weight */
6905 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
6906 if (!peer_group_active(peer)
6907 || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
6908 || peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
6909 if (peer->weight[afi][safi]) {
6910 afi_header_vty_out(vty, afi, safi, write,
6911 " neighbor %s weight %lu\n",
6912 addr,
6913 peer->weight[afi][safi]);
6914 }
6915 }
6916
6917 /* Filter. */
6918 bgp_config_write_filter(vty, peer, afi, safi, write);
6919
6920 /* atribute-unchanged. */
8eeb0335
DW
6921 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
6922 peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ||
6923 peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
6924
6925 if (!peer_group_active(peer) ||
6926 peergroup_af_flag_check(peer, afi, safi,
6927 PEER_FLAG_AS_PATH_UNCHANGED) ||
6928 peergroup_af_flag_check(peer, afi, safi,
6929 PEER_FLAG_NEXTHOP_UNCHANGED) ||
6930 peergroup_af_flag_check(peer, afi, safi,
6931 PEER_FLAG_MED_UNCHANGED)) {
6932
d62a17ae 6933 afi_header_vty_out(
6934 vty, afi, safi, write,
6935 " neighbor %s attribute-unchanged%s%s%s\n",
6936 addr,
8eeb0335 6937 peer_af_flag_check(
d62a17ae 6938 peer, afi, safi,
6939 PEER_FLAG_AS_PATH_UNCHANGED)
6940 ? " as-path"
6941 : "",
8eeb0335 6942 peer_af_flag_check(
d62a17ae 6943 peer, afi, safi,
6944 PEER_FLAG_NEXTHOP_UNCHANGED)
6945 ? " next-hop"
6946 : "",
8eeb0335
DW
6947 peer_af_flag_check(peer, afi, safi,
6948 PEER_FLAG_MED_UNCHANGED)
d62a17ae 6949 ? " med"
6950 : "");
6951 }
6952 }
718e3744 6953}
6954
6955/* Display "address-family" configuration header. */
d62a17ae 6956void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi,
6957 int *write)
6958{
6959 if (*write)
6960 return;
6961
6962 vty_out(vty, " !\n address-family ");
6963
6964 if (afi == AFI_IP) {
6965 if (safi == SAFI_UNICAST)
6966 vty_out(vty, "ipv4 unicast");
6967 else if (safi == SAFI_LABELED_UNICAST)
6968 vty_out(vty, "ipv4 labeled-unicast");
6969 else if (safi == SAFI_MULTICAST)
6970 vty_out(vty, "ipv4 multicast");
6971 else if (safi == SAFI_MPLS_VPN)
6972 vty_out(vty, "ipv4 vpn");
6973 else if (safi == SAFI_ENCAP)
6974 vty_out(vty, "ipv4 encap");
6975 } else if (afi == AFI_IP6) {
6976 if (safi == SAFI_UNICAST)
6977 vty_out(vty, "ipv6 unicast");
6978 else if (safi == SAFI_LABELED_UNICAST)
6979 vty_out(vty, "ipv6 labeled-unicast");
6980 else if (safi == SAFI_MULTICAST)
6981 vty_out(vty, "ipv6 multicast");
6982 else if (safi == SAFI_MPLS_VPN)
6983 vty_out(vty, "ipv6 vpn");
6984 else if (safi == SAFI_ENCAP)
6985 vty_out(vty, "ipv6 encap");
6986 } else if (afi == AFI_L2VPN) {
6987 if (safi == SAFI_EVPN)
6988 vty_out(vty, "l2vpn evpn");
6989 }
6990 vty_out(vty, "\n");
6991
6992 *write = 1;
718e3744 6993}
6994
6995/* Address family based peer configuration display. */
d62a17ae 6996static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
6997 safi_t safi)
718e3744 6998{
d62a17ae 6999 int write = 0;
7000 struct peer *peer;
7001 struct peer_group *group;
7002 struct listnode *node, *nnode;
718e3744 7003
d62a17ae 7004 bgp_config_write_distance(vty, bgp, afi, safi, &write);
734b349e 7005
d62a17ae 7006 bgp_config_write_network(vty, bgp, afi, safi, &write);
718e3744 7007
d62a17ae 7008 bgp_config_write_redistribute(vty, bgp, afi, safi, &write);
718e3744 7009
d62a17ae 7010 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
7011 bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi,
7012 &write);
400b1fad 7013
d62a17ae 7014 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7015 /* Skip dynamic neighbors. */
7016 if (peer_dynamic_neighbor(peer))
7017 continue;
f14e6fdb 7018
d62a17ae 7019 /* Do not display doppelganger peers */
7020 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
7021 bgp_config_write_peer_af(vty, bgp, peer, afi, safi,
7022 &write);
7023 }
165b5fff 7024
d62a17ae 7025 bgp_config_write_maxpaths(vty, bgp, afi, safi, &write);
7026 bgp_config_write_table_map(vty, bgp, afi, safi, &write);
165b5fff 7027
d62a17ae 7028 if (safi == SAFI_EVPN)
7029 bgp_config_write_evpn_info(vty, bgp, afi, safi, &write);
90e60aa7 7030
d62a17ae 7031 if (write)
7032 vty_out(vty, " exit-address-family\n");
718e3744 7033
d62a17ae 7034 return write;
718e3744 7035}
7036
d62a17ae 7037int bgp_config_write(struct vty *vty)
718e3744 7038{
d62a17ae 7039 int write = 0;
7040 struct bgp *bgp;
7041 struct peer_group *group;
7042 struct peer *peer;
7043 struct listnode *node, *nnode;
7044 struct listnode *mnode, *mnnode;
718e3744 7045
d62a17ae 7046 /* BGP Multiple instance. */
7047 if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7048 vty_out(vty, "no bgp multiple-instance\n");
7049 write++;
7050 }
718e3744 7051
d62a17ae 7052 /* BGP Config type. */
7053 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
7054 vty_out(vty, "bgp config-type cisco\n");
7055 write++;
7056 }
718e3744 7057
d62a17ae 7058 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
7059 vty_out(vty, "bgp route-map delay-timer %u\n",
7060 bm->rmap_update_timer);
7061
7062 /* BGP configuration. */
7063 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
7064 if (write)
7065 vty_out(vty, "!\n");
7066
7067 /* Router bgp ASN */
7068 vty_out(vty, "router bgp %u", bgp->as);
7069
7070 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7071 if (bgp->name)
7072 vty_out(vty, " %s %s",
7073 (bgp->inst_type
7074 == BGP_INSTANCE_TYPE_VIEW)
7075 ? "view"
7076 : "vrf",
7077 bgp->name);
7078 }
7079 vty_out(vty, "\n");
7080
7081 /* No Synchronization */
7082 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7083 vty_out(vty, " no synchronization\n");
7084
7085 /* BGP fast-external-failover. */
7086 if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7087 vty_out(vty, " no bgp fast-external-failover\n");
7088
7089 /* BGP router ID. */
7090 if (bgp->router_id_static.s_addr != 0)
7091 vty_out(vty, " bgp router-id %s\n",
7092 inet_ntoa(bgp->router_id_static));
7093
7094 /* BGP log-neighbor-changes. */
7095 if (!!bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7096 != DFLT_BGP_LOG_NEIGHBOR_CHANGES)
7097 vty_out(vty, " %sbgp log-neighbor-changes\n",
7098 bgp_flag_check(bgp,
7099 BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7100 ? ""
7101 : "no ");
7102
7103 /* BGP configuration. */
7104 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7105 vty_out(vty, " bgp always-compare-med\n");
7106
7107 /* BGP default ipv4-unicast. */
7108 if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7109 vty_out(vty, " no bgp default ipv4-unicast\n");
7110
7111 /* BGP default local-preference. */
7112 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7113 vty_out(vty, " bgp default local-preference %u\n",
7114 bgp->default_local_pref);
7115
7116 /* BGP default show-hostname */
7117 if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7118 != DFLT_BGP_SHOW_HOSTNAME)
7119 vty_out(vty, " %sbgp default show-hostname\n",
7120 bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7121 ? ""
7122 : "no ");
7123
7124 /* BGP default subgroup-pkt-queue-max. */
7125 if (bgp->default_subgroup_pkt_queue_max
7126 != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7127 vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
7128 bgp->default_subgroup_pkt_queue_max);
7129
7130 /* BGP client-to-client reflection. */
7131 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7132 vty_out(vty, " no bgp client-to-client reflection\n");
7133
7134 /* BGP cluster ID. */
7135 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
7136 vty_out(vty, " bgp cluster-id %s\n",
7137 inet_ntoa(bgp->cluster_id));
7138
7139 /* Disable ebgp connected nexthop check */
7140 if (bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7141 vty_out(vty,
7142 " bgp disable-ebgp-connected-route-check\n");
7143
7144 /* Confederation identifier*/
7145 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
7146 vty_out(vty, " bgp confederation identifier %i\n",
7147 bgp->confed_id);
7148
7149 /* Confederation peer */
7150 if (bgp->confed_peers_cnt > 0) {
7151 int i;
7152
7153 vty_out(vty, " bgp confederation peers");
7154
7155 for (i = 0; i < bgp->confed_peers_cnt; i++)
7156 vty_out(vty, " %u", bgp->confed_peers[i]);
7157
7158 vty_out(vty, "\n");
7159 }
5fe9f963 7160
d62a17ae 7161 /* BGP enforce-first-as. */
7162 if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS))
7163 vty_out(vty, " bgp enforce-first-as\n");
7164
7165 /* BGP deterministic-med. */
7166 if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7167 != DFLT_BGP_DETERMINISTIC_MED)
7168 vty_out(vty, " %sbgp deterministic-med\n",
7169 bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7170 ? ""
7171 : "no ");
7172
7173 /* BGP update-delay. */
7174 bgp_config_write_update_delay(vty, bgp);
7175
7176 if (bgp->v_maxmed_onstartup
7177 != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) {
7178 vty_out(vty, " bgp max-med on-startup %u",
7179 bgp->v_maxmed_onstartup);
7180 if (bgp->maxmed_onstartup_value
7181 != BGP_MAXMED_VALUE_DEFAULT)
7182 vty_out(vty, " %u",
7183 bgp->maxmed_onstartup_value);
7184 vty_out(vty, "\n");
7185 }
7186 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) {
7187 vty_out(vty, " bgp max-med administrative");
7188 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7189 vty_out(vty, " %u", bgp->maxmed_admin_value);
7190 vty_out(vty, "\n");
7191 }
718e3744 7192
d62a17ae 7193 /* write quanta */
7194 bgp_config_write_wpkt_quanta(vty, bgp);
7195
7196 /* coalesce time */
7197 bgp_config_write_coalesce_time(vty, bgp);
7198
7199 /* BGP graceful-restart. */
7200 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7201 vty_out(vty,
7202 " bgp graceful-restart stalepath-time %u\n",
7203 bgp->stalepath_time);
7204 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
7205 vty_out(vty, " bgp graceful-restart restart-time %u\n",
7206 bgp->restart_time);
7207 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART))
7208 vty_out(vty, " bgp graceful-restart\n");
7209
7210 /* BGP graceful-restart Preserve State F bit. */
7211 if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD))
7212 vty_out(vty,
7213 " bgp graceful-restart preserve-fw-state\n");
7214
7215 /* BGP bestpath method. */
7216 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE))
7217 vty_out(vty, " bgp bestpath as-path ignore\n");
7218 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED))
7219 vty_out(vty, " bgp bestpath as-path confed\n");
7220
7221 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
7222 if (bgp_flag_check(bgp,
7223 BGP_FLAG_MULTIPATH_RELAX_AS_SET)) {
7224 vty_out(vty,
7225 " bgp bestpath as-path multipath-relax as-set\n");
7226 } else {
7227 vty_out(vty,
7228 " bgp bestpath as-path multipath-relax\n");
7229 }
7230 }
718e3744 7231
d62a17ae 7232 if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7233 vty_out(vty,
7234 " bgp route-reflector allow-outbound-policy\n");
7235 }
7236 if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7237 vty_out(vty, " bgp bestpath compare-routerid\n");
7238 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)
7239 || bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) {
7240 vty_out(vty, " bgp bestpath med");
7241 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED))
7242 vty_out(vty, " confed");
7243 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7244 vty_out(vty, " missing-as-worst");
7245 vty_out(vty, "\n");
7246 }
718e3744 7247
d62a17ae 7248 /* BGP network import check. */
7249 if (!!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7250 != DFLT_BGP_IMPORT_CHECK)
7251 vty_out(vty, " %sbgp network import-check\n",
7252 bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7253 ? ""
7254 : "no ");
7255
7256 /* BGP flag dampening. */
7257 if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST],
7258 BGP_CONFIG_DAMPENING))
7259 bgp_config_write_damp(vty);
7260
7261 /* BGP timers configuration. */
7262 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7263 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7264 vty_out(vty, " timers bgp %u %u\n",
7265 bgp->default_keepalive, bgp->default_holdtime);
7266
7267 /* peer-group */
7268 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
7269 bgp_config_write_peer_global(vty, bgp, group->conf);
7270 }
7271
7272 /* Normal neighbor configuration. */
7273 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7274 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
7275 bgp_config_write_peer_global(vty, bgp, peer);
7276 }
718e3744 7277
d62a17ae 7278 /* listen range and limit for dynamic BGP neighbors */
7279 bgp_config_write_listen(vty, bgp);
f14e6fdb 7280
d62a17ae 7281 /* No auto-summary */
7282 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7283 vty_out(vty, " no auto-summary\n");
718e3744 7284
d62a17ae 7285 /* IPv4 unicast configuration. */
7286 write +=
7287 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
0b960b4d 7288
d62a17ae 7289 /* IPv4 multicast configuration. */
7290 write += bgp_config_write_family(vty, bgp, AFI_IP,
7291 SAFI_MULTICAST);
718e3744 7292
d62a17ae 7293 /* IPv4 labeled-unicast configuration. */
7294 write += bgp_config_write_family(vty, bgp, AFI_IP,
7295 SAFI_LABELED_UNICAST);
f51bae9c 7296
d62a17ae 7297 /* IPv4 VPN configuration. */
7298 write += bgp_config_write_family(vty, bgp, AFI_IP,
7299 SAFI_MPLS_VPN);
718e3744 7300
d62a17ae 7301 /* ENCAPv4 configuration. */
7302 write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
8b1fb8be 7303
d62a17ae 7304 /* IPv6 unicast configuration. */
7305 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7306 SAFI_UNICAST);
718e3744 7307
d62a17ae 7308 /* IPv6 multicast configuration. */
7309 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7310 SAFI_MULTICAST);
37a217a5 7311
d62a17ae 7312 /* IPv6 labeled-unicast configuration. */
7313 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7314 SAFI_LABELED_UNICAST);
f51bae9c 7315
d62a17ae 7316 /* IPv6 VPN configuration. */
7317 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7318 SAFI_MPLS_VPN);
8ecd3266 7319
d62a17ae 7320 /* ENCAPv6 configuration. */
7321 write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
8b1fb8be 7322
d62a17ae 7323 /* EVPN configuration. */
7324 write +=
7325 bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
3d6c0dfa 7326
65efcfce 7327#if ENABLE_BGP_VNC
d62a17ae 7328 write += bgp_rfapi_cfg_write(vty, bgp);
65efcfce
LB
7329#endif
7330
d62a17ae 7331 write++;
7332 }
7333 return write;
718e3744 7334}
7335
d62a17ae 7336void bgp_master_init(struct thread_master *master)
718e3744 7337{
d62a17ae 7338 qobj_init();
0e64d123 7339
d62a17ae 7340 memset(&bgp_master, 0, sizeof(struct bgp_master));
718e3744 7341
d62a17ae 7342 bm = &bgp_master;
7343 bm->bgp = list_new();
7344 bm->listen_sockets = list_new();
7345 bm->port = BGP_PORT_DEFAULT;
7346 bm->master = master;
7347 bm->start_time = bgp_clock();
7348 bm->t_rmap_update = NULL;
7349 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
495f0b13 7350
d62a17ae 7351 bgp_process_queue_init();
b8fd6a15 7352
d62a17ae 7353 /* Enable multiple instances by default. */
7354 bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
19df7279 7355
d62a17ae 7356 QOBJ_REG(bm, bgp_master);
718e3744 7357}
200df115 7358
ad4cbda1 7359/*
009b18fc 7360 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7361 * instance delete (non-default only) or BGP exit.
ad4cbda1 7362 */
d62a17ae 7363static void bgp_if_finish(struct bgp *bgp)
ad4cbda1 7364{
d62a17ae 7365 struct listnode *ifnode, *ifnnode;
7366 struct interface *ifp;
7367
7368 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7369 return;
ad4cbda1 7370
d62a17ae 7371 for (ALL_LIST_ELEMENTS(vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp)) {
7372 struct listnode *c_node, *c_nnode;
7373 struct connected *c;
ad4cbda1 7374
d62a17ae 7375 for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
7376 bgp_connected_delete(bgp, c);
7377 }
ad4cbda1 7378}
6b0655a2 7379
d62a17ae 7380extern void bgp_snmp_init(void);
3012671f 7381
d62a17ae 7382static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
18c57037 7383{
d62a17ae 7384 struct vrf *vrf = NULL;
7385 struct listnode *next;
7386 struct bgp *bgp;
18c57037 7387
d62a17ae 7388 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
7389 {
7390 if (vrf->vrf_id != VRF_DEFAULT)
7391 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
7392 }
18c57037 7393
d62a17ae 7394 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
7395 if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
7396 continue;
18c57037 7397
d62a17ae 7398 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name));
7399 }
18c57037
DS
7400}
7401
7402static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = {
d62a17ae 7403 {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete},
7404 {.completions = NULL},
18c57037
DS
7405};
7406
d62a17ae 7407void bgp_init(void)
718e3744 7408{
fc9a856f 7409
d62a17ae 7410 /* allocates some vital data structures used by peer commands in
7411 * vty_init */
718e3744 7412
d62a17ae 7413 /* Init zebra. */
7414 bgp_zebra_init(bm->master);
718e3744 7415
65efcfce 7416#if ENABLE_BGP_VNC
d62a17ae 7417 vnc_zebra_init(bm->master);
65efcfce
LB
7418#endif
7419
d62a17ae 7420 /* BGP VTY commands installation. */
7421 bgp_vty_init();
7422
7423 /* BGP inits. */
7424 bgp_attr_init();
7425 bgp_debug_init();
7426 bgp_dump_init();
7427 bgp_route_init();
7428 bgp_route_map_init();
7429 bgp_scan_vty_init();
7430 bgp_mplsvpn_init();
65efcfce 7431#if ENABLE_BGP_VNC
d62a17ae 7432 rfapi_init();
65efcfce 7433#endif
d62a17ae 7434 bgp_ethernetvpn_init();
7435
7436 /* Access list initialize. */
7437 access_list_init();
7438 access_list_add_hook(peer_distribute_update);
7439 access_list_delete_hook(peer_distribute_update);
7440
7441 /* Filter list initialize. */
7442 bgp_filter_init();
7443 as_list_add_hook(peer_aslist_add);
7444 as_list_delete_hook(peer_aslist_del);
7445
7446 /* Prefix list initialize.*/
7447 prefix_list_init();
7448 prefix_list_add_hook(peer_prefix_list_update);
7449 prefix_list_delete_hook(peer_prefix_list_update);
7450
7451 /* Community list initialize. */
7452 bgp_clist = community_list_init();
7453
7454 /* BFD init */
7455 bgp_bfd_init();
7456
7457 cmd_variable_handler_register(bgp_viewvrf_var_handlers);
7458}
7459
7460void bgp_terminate(void)
7461{
7462 struct bgp *bgp;
7463 struct peer *peer;
7464 struct listnode *node, *nnode;
7465 struct listnode *mnode, *mnnode;
7466
7467 QOBJ_UNREG(bm);
7468
7469 /* Close the listener sockets first as this prevents peers from
7470 * attempting
7471 * to reconnect on receiving the peer unconfig message. In the presence
7472 * of a large number of peers this will ensure that no peer is left with
7473 * a dangling connection
7474 */
7475 /* reverse bgp_master_init */
7476 bgp_close();
7477 if (bm->listen_sockets)
7478 list_free(bm->listen_sockets);
7479 bm->listen_sockets = NULL;
7480
7481 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
7482 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
7483 if (peer->status == Established
7484 || peer->status == OpenSent
7485 || peer->status == OpenConfirm)
7486 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
7487 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
7488
7489 if (bm->process_main_queue) {
7490 work_queue_free(bm->process_main_queue);
7491 bm->process_main_queue = NULL;
7492 }
7493
7494 if (bm->t_rmap_update)
7495 BGP_TIMER_OFF(bm->t_rmap_update);
545acafb 7496}