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