]> git.proxmox.com Git - mirror_frr.git/blame - zebra/connected.c
bgpd: Refactor subgroup_announce_table() to reuse an existing helpers
[mirror_frr.git] / zebra / connected.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
3 * Address linked list routine.
4 * Copyright (C) 1997, 98 Kunihiro Ishiguro
718e3744 5 */
6
7#include <zebra.h>
8
9#include "prefix.h"
10#include "linklist.h"
11#include "if.h"
12#include "table.h"
13#include "rib.h"
14#include "table.h"
15#include "log.h"
0752ef0b 16#include "memory.h"
718e3744 17
82f97584 18#include "vty.h"
b84c7253 19#include "zebra/debug.h"
718e3744 20#include "zebra/zserv.h"
21#include "zebra/redistribute.h"
eef1fe11 22#include "zebra/interface.h"
a1ac18c4 23#include "zebra/connected.h"
b6120505 24#include "zebra/rtadv.h"
40c7bdb0 25#include "zebra/zebra_mpls.h"
9df414fe 26#include "zebra/zebra_errors.h"
e4876266 27#include "zebra/zebra_router.h"
6b0655a2 28
02b4805f 29/* communicate the withdrawal of a connected address */
d62a17ae 30static void connected_withdraw(struct connected *ifc)
ca16218d 31{
d62a17ae 32 if (!ifc)
33 return;
ca16218d 34
d62a17ae 35 /* Update interface address information to protocol daemon. */
36 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
37 zebra_interface_address_delete_update(ifc->ifp, ifc);
ca16218d 38
d62a17ae 39 if (ifc->address->family == AF_INET)
40 if_subnet_delete(ifc->ifp, ifc);
9db047fc 41
11461c63 42 connected_down(ifc->ifp, ifc);
ca16218d 43
d62a17ae 44 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
45 }
ca16218d 46
d62a17ae 47 /* The address is not in the kernel anymore, so clear the flag */
48 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
f7f740fe 49
d62a17ae 50 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
51 listnode_delete(ifc->ifp->connected, ifc);
721c0857 52 connected_free(&ifc);
d62a17ae 53 }
ca16218d 54}
55
d62a17ae 56static void connected_announce(struct interface *ifp, struct connected *ifc)
ca16218d 57{
d62a17ae 58 if (!ifc)
59 return;
60
608c8870 61 if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) {
12256b84 62 if (ifc->address->prefixlen == IPV4_MAX_BITLEN)
d62a17ae 63 SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
64 else
65 UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
66 }
67
68 listnode_add(ifp->connected, ifc);
69
70 /* Update interface address information to protocol daemon. */
71 if (ifc->address->family == AF_INET)
72 if_subnet_add(ifp, ifc);
73
74 zebra_interface_address_add_update(ifp, ifc);
75
76 if (if_is_operative(ifp)) {
ae87977c 77 connected_up(ifp, ifc);
d62a17ae 78 }
ca16218d 79}
6b0655a2 80
718e3744 81/* If same interface address is already exist... */
abffde07
DL
82struct connected *connected_check(struct interface *ifp,
83 union prefixconstptr pu)
718e3744 84{
abffde07 85 const struct prefix *p = pu.p;
d62a17ae 86 struct connected *ifc;
87 struct listnode *node;
718e3744 88
d62a17ae 89 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
90 if (prefix_same(ifc->address, p))
91 return ifc;
718e3744 92
d62a17ae 93 return NULL;
718e3744 94}
95
abffde07
DL
96/* same, but with peer address */
97struct connected *connected_check_ptp(struct interface *ifp,
98 union prefixconstptr pu,
99 union prefixconstptr du)
100{
101 const struct prefix *p = pu.p;
102 const struct prefix *d = du.p;
103 struct connected *ifc;
104 struct listnode *node;
105
abffde07
DL
106 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
107 if (!prefix_same(ifc->address, p))
108 continue;
109 if (!CONNECTED_PEER(ifc) && !d)
110 return ifc;
111 if (CONNECTED_PEER(ifc) && d
112 && prefix_same(ifc->destination, d))
113 return ifc;
114 }
115
116 return NULL;
117}
118
02b4805f 119/* Check if two ifc's describe the same address in the same state */
d62a17ae 120static int connected_same(struct connected *ifc1, struct connected *ifc2)
74ecdc9e 121{
d62a17ae 122 if (ifc1->ifp != ifc2->ifp)
123 return 0;
124
0f3af738
JW
125 if (ifc1->flags != ifc2->flags)
126 return 0;
127
128 if (ifc1->conf != ifc2->conf)
129 return 0;
130
d62a17ae 131 if (ifc1->destination)
132 if (!ifc2->destination)
133 return 0;
134 if (ifc2->destination)
135 if (!ifc1->destination)
136 return 0;
137
138 if (ifc1->destination && ifc2->destination)
139 if (!prefix_same(ifc1->destination, ifc2->destination))
140 return 0;
141
d62a17ae 142 return 1;
74ecdc9e
PJ
143}
144
d7f5dad6
CF
145/* Handle changes to addresses and send the neccesary announcements
146 * to clients. */
d62a17ae 147static void connected_update(struct interface *ifp, struct connected *ifc)
74ecdc9e 148{
d62a17ae 149 struct connected *current;
150
151 /* Check same connected route. */
abffde07
DL
152 current = connected_check_ptp(ifp, ifc->address, ifc->destination);
153 if (current) {
d62a17ae 154 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
155 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
156
157 /* Avoid spurious withdraws, this might be just the kernel
158 * 'reflecting'
159 * back an address we have already added.
160 */
161 if (connected_same(current, ifc)) {
162 /* nothing to do */
721c0857 163 connected_free(&ifc);
d62a17ae 164 return;
165 }
166
167 /* Clear the configured flag on the old ifc, so it will be freed
168 * by
169 * connected withdraw. */
170 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
171 connected_withdraw(
172 current); /* implicit withdraw - freebsd does this */
173 }
174
175 /* If the connected is new or has changed, announce it, if it is usable
176 */
177 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
178 connected_announce(ifp, ifc);
74ecdc9e
PJ
179}
180
718e3744 181/* Called from if_up(). */
ae87977c 182void connected_up(struct interface *ifp, struct connected *ifc)
718e3744 183{
ae87977c 184 afi_t afi;
b08dcc3f 185 struct prefix p;
fd36be7e 186 struct nexthop nh = {
4a7371e9
DS
187 .type = NEXTHOP_TYPE_IFINDEX,
188 .ifindex = ifp->ifindex,
096f7609 189 .vrf_id = ifp->vrf->vrf_id,
fd36be7e 190 };
56e78254 191 struct zebra_vrf *zvrf;
cde1af84 192 uint32_t metric;
e4876266 193 uint32_t flags = 0;
92980561
DS
194 uint32_t count = 0;
195 struct listnode *cnode;
196 struct connected *c;
d62a17ae 197
096f7609 198 zvrf = ifp->vrf->info;
56e78254 199 if (!zvrf) {
15569c58
DA
200 flog_err(
201 EC_ZEBRA_VRF_NOT_FOUND,
096f7609
IR
202 "%s: Received Up for interface but no associated zvrf: %s(%d)",
203 __func__, ifp->vrf->name, ifp->vrf->vrf_id);
56e78254
DS
204 return;
205 }
d62a17ae 206 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
207 return;
208
e3d901f8
MS
209 /* Ensure 'down' flag is cleared */
210 UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
211
b08dcc3f 212 prefix_copy(&p, CONNECTED_PREFIX(ifc));
d62a17ae 213
214 /* Apply mask to the network. */
215 apply_mask(&p);
216
ae87977c
DS
217 afi = family2afi(p.family);
218
219 switch (afi) {
220 case AFI_IP:
221 /*
222 * In case of connected address is 0.0.0.0/0 we treat it tunnel
223 * address.
224 */
225 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
226 return;
227 break;
228 case AFI_IP6:
70bc8385 229#ifndef GNU_LINUX
ae87977c
DS
230 /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
231 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
232 return;
233#endif
234 break;
a98701f0
DS
235 case AFI_UNSPEC:
236 case AFI_L2VPN:
237 case AFI_MAX:
e914ccbe 238 flog_warn(EC_ZEBRA_CONNECTED_AFI_UNKNOWN,
9df414fe 239 "Received unknown AFI: %s", afi2str(afi));
d62a17ae 240 return;
ae87977c
DS
241 break;
242 }
d62a17ae 243
cde1af84
AK
244 metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
245 ifc->metric : ifp->metric;
d62a17ae 246
e4876266
DS
247 /*
248 * Since we are hand creating the connected routes
249 * in our main routing table, *if* we are working
250 * in an offloaded environment then we need to
251 * pretend like the route is offloaded so everything
252 * else will work
253 */
254 if (zrouter.asic_offloaded)
255 flags |= ZEBRA_FLAG_OFFLOADED;
256
92980561
DS
257 /*
258 * It's possible to add the same network and mask
259 * to an interface over and over. This would
260 * result in an equivalent number of connected
261 * routes. Just add one connected route in
262 * for all the addresses on an interface that
263 * resolve to the same network and mask
264 */
265 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
b08dcc3f 266 struct prefix cp;
92980561 267
b08dcc3f 268 prefix_copy(&cp, CONNECTED_PREFIX(c));
92980561
DS
269 apply_mask(&cp);
270
e3d901f8
MS
271 if (prefix_same(&cp, &p) &&
272 !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
92980561
DS
273 count++;
274
275 if (count >= 2)
276 return;
277 }
278
e4876266 279 rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
c6eee91f
DS
280 flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
281 false);
e4876266
DS
282
283 rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
c6eee91f
DS
284 flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
285 false);
d62a17ae 286
d62a17ae 287 /* Schedule LSP forwarding entries for processing, if appropriate. */
56e78254 288 if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
2dbe669b 289 if (IS_ZEBRA_DEBUG_MPLS)
996c9314 290 zlog_debug(
2dbe669b
DA
291 "%u: IF %s IP %pFX address add/up, scheduling MPLS processing",
292 zvrf->vrf->vrf_id, ifp->name, &p);
56e78254 293 mpls_mark_lsps_for_processing(zvrf, &p);
d62a17ae 294 }
718e3744 295}
296
297/* Add connected IPv4 route to the interface. */
9c86ee1e
MS
298void connected_add_ipv4(struct interface *ifp, int flags,
299 const struct in_addr *addr, uint16_t prefixlen,
300 const struct in_addr *dest, const char *label,
301 uint32_t metric)
718e3744 302{
d62a17ae 303 struct prefix_ipv4 *p;
304 struct connected *ifc;
305
306 if (ipv4_martian(addr))
307 return;
308
309 /* Make connected structure. */
310 ifc = connected_new();
311 ifc->ifp = ifp;
312 ifc->flags = flags;
cde1af84 313 ifc->metric = metric;
d62a17ae 314 /* If we get a notification from the kernel,
315 * we can safely assume the address is known to the kernel */
316 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
7fb9825c
VH
317 if (!if_is_operative(ifp))
318 SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
d62a17ae 319
320 /* Allocate new connected address. */
321 p = prefix_ipv4_new();
322 p->family = AF_INET;
323 p->prefix = *addr;
936fbaef
DA
324 p->prefixlen =
325 CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_BITLEN : prefixlen;
d62a17ae 326 ifc->address = (struct prefix *)p;
327
0f3af738
JW
328 /* If there is a peer address. */
329 if (CONNECTED_PEER(ifc)) {
d62a17ae 330 /* validate the destination address */
0f3af738
JW
331 if (dest) {
332 p = prefix_ipv4_new();
333 p->family = AF_INET;
334 p->prefix = *dest;
335 p->prefixlen = prefixlen;
336 ifc->destination = (struct prefix *)p;
337
338 if (IPV4_ADDR_SAME(addr, dest))
9df414fe 339 flog_warn(
e914ccbe 340 EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER,
ad6f7449 341 "interface %s has same local and peer address %pI4, routing protocols may malfunction",
9bcef951 342 ifp->name, addr);
d62a17ae 343 } else {
9df414fe 344 zlog_debug(
ad6f7449 345 "%s called for interface %s with peer flag set, but no peer address supplied",
d62a17ae 346 __func__, ifp->name);
347 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
348 }
e4529636
AS
349 }
350
0f3af738 351 /* no destination address was supplied */
936fbaef 352 if (!dest && (prefixlen == IPV4_MAX_BITLEN) && if_is_pointopoint(ifp))
0f3af738 353 zlog_debug(
ad6f7449 354 "PtP interface %s with addr %pI4/%d needs a peer address",
9bcef951 355 ifp->name, addr, prefixlen);
0f3af738 356
d62a17ae 357 /* Label of this address. */
358 if (label)
359 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 360
d62a17ae 361 /* For all that I know an IPv4 address is always ready when we receive
362 * the notification. So it should be safe to set the REAL flag here. */
363 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
718e3744 364
d62a17ae 365 connected_update(ifp, ifc);
718e3744 366}
367
11461c63 368void connected_down(struct interface *ifp, struct connected *ifc)
718e3744 369{
11461c63 370 afi_t afi;
d62a17ae 371 struct prefix p;
fd36be7e 372 struct nexthop nh = {
4a7371e9
DS
373 .type = NEXTHOP_TYPE_IFINDEX,
374 .ifindex = ifp->ifindex,
096f7609 375 .vrf_id = ifp->vrf->vrf_id,
fd36be7e 376 };
2bb8b49c
DS
377 struct zebra_vrf *zvrf;
378 uint32_t count = 0;
92980561
DS
379 struct listnode *cnode;
380 struct connected *c;
56e78254 381
096f7609 382 zvrf = ifp->vrf->info;
56e78254 383 if (!zvrf) {
15569c58
DA
384 flog_err(
385 EC_ZEBRA_VRF_NOT_FOUND,
096f7609
IR
386 "%s: Received Down for interface but no associated zvrf: %s(%d)",
387 __func__, ifp->vrf->name, ifp->vrf->vrf_id);
56e78254
DS
388 return;
389 }
718e3744 390
d62a17ae 391 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
392 return;
718e3744 393
e3d901f8
MS
394 /* Skip if we've already done this; this can happen if we have a
395 * config change that takes an interface down, then we receive kernel
396 * notifications about the downed interface and its addresses.
397 */
398 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_DOWN)) {
399 if (IS_ZEBRA_DEBUG_RIB)
400 zlog_debug("%s: ifc %p, %pFX already DOWN",
401 __func__, ifc, ifc->address);
402 return;
403 }
404
b08dcc3f 405 prefix_copy(&p, CONNECTED_PREFIX(ifc));
718e3744 406
d62a17ae 407 /* Apply mask to the network. */
408 apply_mask(&p);
718e3744 409
11461c63
DS
410 afi = family2afi(p.family);
411
412 switch (afi) {
413 case AFI_IP:
414 /*
415 * In case of connected address is 0.0.0.0/0 we treat it tunnel
416 * address.
417 */
418 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
419 return;
420 break;
421 case AFI_IP6:
422 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
423 return;
424 break;
a98701f0
DS
425 case AFI_UNSPEC:
426 case AFI_L2VPN:
427 case AFI_MAX:
14a4d9d0 428 zlog_warn("Unknown AFI: %s", afi2str(afi));
11461c63
DS
429 break;
430 }
718e3744 431
e3d901f8
MS
432 /* Mark the address as 'down' */
433 SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
434
92980561
DS
435 /*
436 * It's possible to have X number of addresses
437 * on a interface that all resolve to the same
438 * network and mask. Find them and just
439 * allow the deletion when are removing the last
440 * one.
441 */
442 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
443 struct prefix cp;
444
b08dcc3f 445 prefix_copy(&cp, CONNECTED_PREFIX(c));
92980561
DS
446 apply_mask(&cp);
447
2bb8b49c
DS
448 if (prefix_same(&p, &cp) &&
449 !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
450 count++;
92980561 451
2bb8b49c 452 if (count >= 1)
92980561
DS
453 return;
454 }
455
11461c63
DS
456 /*
457 * Same logic as for connected_up(): push the changes into the
458 * head.
459 */
bc541126 460 rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
3ceae22b 461 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
718e3744 462
56e78254 463 rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
3ceae22b 464 0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
42cb6b66 465
d62a17ae 466 /* Schedule LSP forwarding entries for processing, if appropriate. */
56e78254 467 if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
2dbe669b 468 if (IS_ZEBRA_DEBUG_MPLS)
996c9314 469 zlog_debug(
2dbe669b
DA
470 "%u: IF %s IP %pFX address down, scheduling MPLS processing",
471 zvrf->vrf->vrf_id, ifp->name, &p);
56e78254 472 mpls_mark_lsps_for_processing(zvrf, &p);
d62a17ae 473 }
718e3744 474}
475
dc7cd304
DS
476static void connected_delete_helper(struct connected *ifc, struct prefix *p)
477{
478 struct interface *ifp;
479
480 if (!ifc)
481 return;
482 ifp = ifc->ifp;
483
484 connected_withdraw(ifc);
485
dc7cd304 486 /* Schedule LSP forwarding entries for processing, if appropriate. */
096f7609 487 if (ifp->vrf->vrf_id == VRF_DEFAULT) {
2dbe669b 488 if (IS_ZEBRA_DEBUG_MPLS)
996c9314 489 zlog_debug(
2dbe669b 490 "%u: IF %s IP %pFX address delete, scheduling MPLS processing",
096f7609
IR
491 ifp->vrf->vrf_id, ifp->name, p);
492 mpls_mark_lsps_for_processing(ifp->vrf->info, p);
dc7cd304
DS
493 }
494}
495
718e3744 496/* Delete connected IPv4 route to the interface. */
d62a17ae 497void connected_delete_ipv4(struct interface *ifp, int flags,
9c86ee1e
MS
498 const struct in_addr *addr, uint16_t prefixlen,
499 const struct in_addr *dest)
718e3744 500{
dc7cd304 501 struct prefix p, d;
d62a17ae 502 struct connected *ifc;
503
6006b807 504 memset(&p, 0, sizeof(p));
d62a17ae 505 p.family = AF_INET;
dc7cd304 506 p.u.prefix4 = *addr;
936fbaef
DA
507 p.prefixlen =
508 CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_BITLEN : prefixlen;
abffde07 509
0f3af738 510 if (dest) {
6006b807 511 memset(&d, 0, sizeof(d));
abffde07 512 d.family = AF_INET;
0f3af738 513 d.u.prefix4 = *dest;
abffde07 514 d.prefixlen = prefixlen;
dc7cd304 515 ifc = connected_check_ptp(ifp, &p, &d);
abffde07 516 } else
dc7cd304 517 ifc = connected_check_ptp(ifp, &p, NULL);
d62a17ae 518
dc7cd304 519 connected_delete_helper(ifc, &p);
718e3744 520}
521
718e3744 522/* Add connected IPv6 route to the interface. */
9c86ee1e
MS
523void connected_add_ipv6(struct interface *ifp, int flags,
524 const struct in6_addr *addr,
525 const struct in6_addr *dest, uint16_t prefixlen,
cde1af84 526 const char *label, uint32_t metric)
718e3744 527{
d62a17ae 528 struct prefix_ipv6 *p;
529 struct connected *ifc;
530
531 if (ipv6_martian(addr))
532 return;
533
534 /* Make connected structure. */
535 ifc = connected_new();
536 ifc->ifp = ifp;
537 ifc->flags = flags;
cde1af84 538 ifc->metric = metric;
d62a17ae 539 /* If we get a notification from the kernel,
540 * we can safely assume the address is known to the kernel */
541 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
7fb9825c
VH
542 if (!if_is_operative(ifp))
543 SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
d62a17ae 544
545 /* Allocate new connected address. */
546 p = prefix_ipv6_new();
547 p->family = AF_INET6;
548 IPV6_ADDR_COPY(&p->prefix, addr);
549 p->prefixlen = prefixlen;
550 ifc->address = (struct prefix *)p;
551
2a855763
DS
552 /* Add global ipv6 address to the RA prefix list */
553 if (!IN6_IS_ADDR_LINKLOCAL(&p->prefix))
554 rtadv_add_prefix(ifp->info, p);
555
0f3af738 556 if (dest) {
60c0687a
DS
557 p = prefix_ipv6_new();
558 p->family = AF_INET6;
0f3af738 559 IPV6_ADDR_COPY(&p->prefix, dest);
60c0687a
DS
560 p->prefixlen = prefixlen;
561 ifc->destination = (struct prefix *)p;
f52d0a1a
DS
562 } else {
563 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
9df414fe 564 zlog_debug(
ad6f7449 565 "%s called for interface %s with peer flag set, but no peer address supplied",
9df414fe 566 __func__, ifp->name);
f52d0a1a
DS
567 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
568 }
60c0687a
DS
569 }
570
d62a17ae 571 /* Label of this address. */
572 if (label)
573 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
574
575 /* On Linux, we only get here when DAD is complete, therefore we can set
576 * ZEBRA_IFC_REAL.
577 *
578 * On BSD, there currently doesn't seem to be a way to check for
579 * completion of
580 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL,
581 * although DAD
582 * might still be running.
583 */
584 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
585 connected_update(ifp, ifc);
718e3744 586}
587
9c86ee1e
MS
588void connected_delete_ipv6(struct interface *ifp,
589 const struct in6_addr *address,
590 const struct in6_addr *dest, uint16_t prefixlen)
718e3744 591{
60c0687a 592 struct prefix p, d;
d62a17ae 593 struct connected *ifc;
594
6006b807 595 memset(&p, 0, sizeof(p));
d62a17ae 596 p.family = AF_INET6;
dc7cd304 597 memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
d62a17ae 598 p.prefixlen = prefixlen;
599
2a855763
DS
600 /* Delete global ipv6 address from RA prefix list */
601 if (!IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
602 rtadv_delete_prefix(ifp->info, &p);
603
0f3af738 604 if (dest) {
6006b807 605 memset(&d, 0, sizeof(d));
60c0687a 606 d.family = AF_INET6;
0f3af738 607 IPV6_ADDR_COPY(&d.u.prefix6, dest);
60c0687a
DS
608 d.prefixlen = prefixlen;
609 ifc = connected_check_ptp(ifp, &p, &d);
610 } else
611 ifc = connected_check_ptp(ifp, &p, NULL);
d62a17ae 612
dc7cd304 613 connected_delete_helper(ifc, &p);
718e3744 614}
d44ca835 615
d62a17ae 616int connected_is_unnumbered(struct interface *ifp)
d44ca835 617{
d62a17ae 618 struct connected *connected;
619 struct listnode *node;
620
621 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
622 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
623 && connected->address->family == AF_INET)
624 return CHECK_FLAG(connected->flags,
625 ZEBRA_IFA_UNNUMBERED);
626 }
a79fdd65 627 return 0;
d44ca835 628}