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