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