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