]> git.proxmox.com Git - mirror_frr.git/blob - zebra/ioctl.c
tools: config clang-format to allow aligned macros
[mirror_frr.git] / zebra / ioctl.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Common ioctl functions.
4 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 */
6
7 #include <zebra.h>
8
9 #include "linklist.h"
10 #include "if.h"
11 #include "prefix.h"
12 #include "ioctl.h"
13 #include "log.h"
14 #include "privs.h"
15 #include "lib_errors.h"
16
17 #include "vty.h"
18 #include "zebra/rib.h"
19 #include "zebra/rt.h"
20 #include "zebra/interface.h"
21 #include "zebra/zebra_errors.h"
22 #include "zebra/debug.h"
23
24 #ifdef HAVE_BSD_LINK_DETECT
25 #include <net/if_media.h>
26 #endif /* HAVE_BSD_LINK_DETECT*/
27
28 extern struct zebra_privs_t zserv_privs;
29
30 /* clear and set interface name string */
31 void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp)
32 {
33 strlcpy(ifreq->ifr_name, ifp->name, sizeof(ifreq->ifr_name));
34 }
35
36 #ifndef HAVE_NETLINK
37 /* call ioctl system call */
38 int if_ioctl(unsigned long request, caddr_t buffer)
39 {
40 int sock;
41 int ret;
42 int err = 0;
43
44 frr_with_privs(&zserv_privs) {
45 sock = socket(AF_INET, SOCK_DGRAM, 0);
46 if (sock < 0) {
47 zlog_err("Cannot create UDP socket: %s",
48 safe_strerror(errno));
49 exit(1);
50 }
51 if ((ret = ioctl(sock, request, buffer)) < 0)
52 err = errno;
53 }
54 close(sock);
55
56 if (ret < 0) {
57 errno = err;
58 return ret;
59 }
60 return 0;
61 }
62 #endif
63
64 /* call ioctl system call */
65 int vrf_if_ioctl(unsigned long request, caddr_t buffer, vrf_id_t vrf_id)
66 {
67 int sock;
68 int ret;
69 int err = 0;
70
71 frr_with_privs(&zserv_privs) {
72 sock = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
73 if (sock < 0) {
74 zlog_err("Cannot create UDP socket: %s",
75 safe_strerror(errno));
76 exit(1);
77 }
78 ret = vrf_ioctl(vrf_id, sock, request, buffer);
79 if (ret < 0)
80 err = errno;
81 }
82 close(sock);
83
84 if (ret < 0) {
85 errno = err;
86 return ret;
87 }
88 return 0;
89 }
90
91 #ifndef HAVE_NETLINK
92 static int if_ioctl_ipv6(unsigned long request, caddr_t buffer)
93 {
94 int sock;
95 int ret;
96 int err = 0;
97
98 frr_with_privs(&zserv_privs) {
99 sock = socket(AF_INET6, SOCK_DGRAM, 0);
100 if (sock < 0) {
101 zlog_err("Cannot create IPv6 datagram socket: %s",
102 safe_strerror(errno));
103 exit(1);
104 }
105
106 if ((ret = ioctl(sock, request, buffer)) < 0)
107 err = errno;
108 }
109 close(sock);
110
111 if (ret < 0) {
112 errno = err;
113 return ret;
114 }
115 return 0;
116 }
117
118 /*
119 * get interface metric
120 * -- if value is not avaliable set -1
121 */
122 void if_get_metric(struct interface *ifp)
123 {
124 #ifdef SIOCGIFMETRIC
125 struct ifreq ifreq = {};
126
127 ifreq_set_name(&ifreq, ifp);
128
129 if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf->vrf_id) < 0)
130 return;
131 ifp->metric = ifreq.ifr_metric;
132 if (ifp->metric == 0)
133 ifp->metric = 1;
134 #else /* SIOCGIFMETRIC */
135 ifp->metric = -1;
136 #endif /* SIOCGIFMETRIC */
137 }
138
139 /* get interface MTU */
140 void if_get_mtu(struct interface *ifp)
141 {
142 struct ifreq ifreq = {};
143
144 ifreq_set_name(&ifreq, ifp);
145
146 #if defined(SIOCGIFMTU)
147 if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf->vrf_id) < 0) {
148 zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU) for %s(%u)",
149 ifp->name, ifp->vrf->vrf_id);
150 ifp->mtu6 = ifp->mtu = -1;
151 return;
152 }
153
154 ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu;
155
156 /* propogate */
157 zebra_interface_up_update(ifp);
158
159 #else
160 zlog_info("Can't lookup mtu on this system for %s(%u)", ifp->name,
161 ifp->vrf->vrf_id);
162 ifp->mtu6 = ifp->mtu = -1;
163 #endif
164 }
165 #endif /* ! HAVE_NETLINK */
166
167 /*
168 * Handler for interface address programming via the zebra dplane,
169 * for non-netlink platforms. This handler dispatches to per-platform
170 * helpers, based on the operation requested.
171 */
172 #ifndef HAVE_NETLINK
173
174 /* Prototypes: these are placed in this block so that they're only seen
175 * on non-netlink platforms.
176 */
177 static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx);
178 static int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx);
179 static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx);
180 static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx);
181
182 enum zebra_dplane_result kernel_address_update_ctx(
183 struct zebra_dplane_ctx *ctx)
184 {
185 int ret = -1;
186 const struct prefix *p;
187
188 p = dplane_ctx_get_intf_addr(ctx);
189
190 if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_INSTALL) {
191 if (p->family == AF_INET)
192 ret = if_set_prefix_ctx(ctx);
193 else
194 ret = if_set_prefix6_ctx(ctx);
195 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_UNINSTALL) {
196 if (p->family == AF_INET)
197 ret = if_unset_prefix_ctx(ctx);
198 else
199 ret = if_unset_prefix6_ctx(ctx);
200 } else {
201 if (IS_ZEBRA_DEBUG_DPLANE)
202 zlog_debug("Invalid op in interface-addr install");
203 }
204
205 return (ret == 0 ?
206 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
207 }
208
209 #ifdef HAVE_STRUCT_IFALIASREQ
210
211 /*
212 * Helper for interface-addr install, non-netlink
213 */
214 static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx)
215 {
216 int ret;
217 struct ifaliasreq addreq;
218 struct sockaddr_in addr, mask, peer;
219 struct prefix_ipv4 *p;
220
221 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
222
223 memset(&addreq, 0, sizeof(addreq));
224 strlcpy((char *)&addreq.ifra_name, dplane_ctx_get_ifname(ctx),
225 sizeof(addreq.ifra_name));
226
227 memset(&addr, 0, sizeof(addr));
228 addr.sin_addr = p->prefix;
229 addr.sin_family = p->family;
230 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
231 addr.sin_len = sizeof(struct sockaddr_in);
232 #endif
233 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
234
235 if (dplane_ctx_intf_is_connected(ctx)) {
236 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_dest(ctx);
237 memset(&mask, 0, sizeof(mask));
238 peer.sin_addr = p->prefix;
239 peer.sin_family = p->family;
240 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
241 peer.sin_len = sizeof(struct sockaddr_in);
242 #endif
243 memcpy(&addreq.ifra_broadaddr, &peer,
244 sizeof(struct sockaddr_in));
245 }
246
247 memset(&mask, 0, sizeof(mask));
248 masklen2ip(p->prefixlen, &mask.sin_addr);
249 mask.sin_family = p->family;
250 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
251 mask.sin_len = sizeof(struct sockaddr_in);
252 #endif
253 memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
254
255 ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq);
256 if (ret < 0)
257 return ret;
258 return 0;
259
260 }
261
262 /*
263 * Helper for interface-addr un-install, non-netlink
264 */
265 static int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx)
266 {
267 int ret;
268 struct ifaliasreq addreq;
269 struct sockaddr_in addr, mask, peer;
270 struct prefix_ipv4 *p;
271
272 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
273
274 memset(&addreq, 0, sizeof(addreq));
275 strlcpy((char *)&addreq.ifra_name, dplane_ctx_get_ifname(ctx),
276 sizeof(addreq.ifra_name));
277
278 memset(&addr, 0, sizeof(addr));
279 addr.sin_addr = p->prefix;
280 addr.sin_family = p->family;
281 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
282 addr.sin_len = sizeof(struct sockaddr_in);
283 #endif
284 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
285
286 if (dplane_ctx_intf_is_connected(ctx)) {
287 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_dest(ctx);
288 memset(&mask, 0, sizeof(mask));
289 peer.sin_addr = p->prefix;
290 peer.sin_family = p->family;
291 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
292 peer.sin_len = sizeof(struct sockaddr_in);
293 #endif
294 memcpy(&addreq.ifra_broadaddr, &peer,
295 sizeof(struct sockaddr_in));
296 }
297
298 memset(&mask, 0, sizeof(mask));
299 masklen2ip(p->prefixlen, &mask.sin_addr);
300 mask.sin_family = p->family;
301 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
302 mask.sin_len = sizeof(struct sockaddr_in);
303 #endif
304 memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
305
306 ret = if_ioctl(SIOCDIFADDR, (caddr_t)&addreq);
307 if (ret < 0)
308 return ret;
309 return 0;
310 }
311 #else
312 /* Set up interface's address, netmask (and broadcas? ). Linux or
313 Solaris uses ifname:number semantics to set IP address aliases. */
314 int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx)
315 {
316 int ret;
317 struct ifreq ifreq;
318 struct sockaddr_in addr;
319 struct sockaddr_in broad;
320 struct sockaddr_in mask;
321 struct prefix_ipv4 ifaddr;
322 struct prefix_ipv4 *p;
323
324 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
325
326 ifaddr = *p;
327
328 strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx),
329 sizeof(ifreq.ifr_name));
330
331 addr.sin_addr = p->prefix;
332 addr.sin_family = p->family;
333 memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
334 ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
335 if (ret < 0)
336 return ret;
337
338 /* We need mask for make broadcast addr. */
339 masklen2ip(p->prefixlen, &mask.sin_addr);
340
341 if (dplane_ctx_intf_is_broadcast(ctx)) {
342 apply_mask_ipv4(&ifaddr);
343 addr.sin_addr = ifaddr.prefix;
344
345 broad.sin_addr.s_addr =
346 (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
347 broad.sin_family = p->family;
348
349 memcpy(&ifreq.ifr_broadaddr, &broad,
350 sizeof(struct sockaddr_in));
351 ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq);
352 if (ret < 0)
353 return ret;
354 }
355
356 mask.sin_family = p->family;
357 memcpy(&ifreq.ifr_addr, &mask, sizeof(struct sockaddr_in));
358 ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq);
359 if (ret < 0)
360 return ret;
361
362 return 0;
363 }
364
365 /* Set up interface's address, netmask (and broadcas? ). Linux or
366 Solaris uses ifname:number semantics to set IP address aliases. */
367 int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx)
368 {
369 int ret;
370 struct ifreq ifreq;
371 struct sockaddr_in addr;
372 struct prefix_ipv4 *p;
373
374 p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx);
375
376 strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx),
377 sizeof(ifreq.ifr_name));
378
379 memset(&addr, 0, sizeof(addr));
380 addr.sin_family = p->family;
381 memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
382 ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
383 if (ret < 0)
384 return ret;
385
386 return 0;
387 }
388 #endif /* HAVE_STRUCT_IFALIASREQ */
389 #endif /* HAVE_NETLINK */
390
391 /* get interface flags */
392 void if_get_flags(struct interface *ifp)
393 {
394 int ret;
395 struct ifreq ifreqflags = {};
396 struct ifreq ifreqdata = {};
397
398 ifreq_set_name(&ifreqflags, ifp);
399 ifreq_set_name(&ifreqdata, ifp);
400
401 ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreqflags,
402 ifp->vrf->vrf_id);
403 if (ret < 0) {
404 flog_err_sys(EC_LIB_SYSTEM_CALL,
405 "vrf_if_ioctl(SIOCGIFFLAGS %s) failed: %s",
406 ifp->name, safe_strerror(errno));
407 return;
408 }
409
410 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
411 goto out;
412
413 /* Per-default, IFF_RUNNING is held high, unless link-detect
414 * says otherwise - we abuse IFF_RUNNING inside zebra as a
415 * link-state flag, following practice on Linux and Solaris
416 * kernels
417 */
418
419 #ifdef SIOCGIFDATA
420 /*
421 * BSD gets link state from ifi_link_link in struct if_data.
422 * All BSD's have this in getifaddrs(3) ifa_data for AF_LINK
423 * addresses. We can also access it via SIOCGIFDATA.
424 */
425
426 #ifdef __NetBSD__
427 struct ifdatareq ifdr = {.ifdr_data.ifi_link_state = 0};
428 struct if_data *ifdata = &ifdr.ifdr_data;
429
430 strlcpy(ifdr.ifdr_name, ifp->name, sizeof(ifdr.ifdr_name));
431 ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifdr, ifp->vrf->vrf_id);
432 #else
433 struct if_data ifd = {.ifi_link_state = 0};
434 struct if_data *ifdata = &ifd;
435
436 ifreqdata.ifr_data = (caddr_t)ifdata;
437 ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreqdata, ifp->vrf->vrf_id);
438 #endif
439
440 if (ret == -1)
441 /* Very unlikely. Did the interface disappear? */
442 flog_err_sys(EC_LIB_SYSTEM_CALL,
443 "if_ioctl(SIOCGIFDATA %s) failed: %s", ifp->name,
444 safe_strerror(errno));
445 else {
446 if (ifdata->ifi_link_state >= LINK_STATE_UP)
447 SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
448 else if (ifdata->ifi_link_state == LINK_STATE_UNKNOWN)
449 /* BSD traditionally treats UNKNOWN as UP */
450 SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
451 else
452 UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
453 }
454
455 #elif defined(HAVE_BSD_LINK_DETECT)
456 /*
457 * This is only needed for FreeBSD older than FreeBSD-13.
458 * Valid and active media generally means the link state is
459 * up, but this is not always the case.
460 * For example, some BSD's with a net80211 interface in MONITOR
461 * mode will treat the media as valid and active but the
462 * link state is down - because we cannot send anything.
463 * Also, virtual interfaces such as PPP, VLAN, etc generally
464 * don't support media at all, so the ioctl will just fail.
465 */
466 struct ifmediareq ifmr = {.ifm_status = 0};
467
468 strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
469
470 if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
471 if (errno != EINVAL)
472 flog_err_sys(EC_LIB_SYSTEM_CALL,
473 "if_ioctl(SIOCGIFMEDIA %s) failed: %s",
474 ifp->name, safe_strerror(errno));
475 } else if (ifmr.ifm_status & IFM_AVALID) { /* media state is valid */
476 if (ifmr.ifm_status & IFM_ACTIVE) /* media is active */
477 SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
478 else
479 UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
480 }
481 #endif /* HAVE_BSD_LINK_DETECT */
482
483 out:
484 if_flags_update(ifp, (ifreqflags.ifr_flags & 0x0000ffff));
485 }
486
487 /* Set interface flags */
488 int if_set_flags(struct interface *ifp, uint64_t flags)
489 {
490 int ret;
491 struct ifreq ifreq;
492
493 memset(&ifreq, 0, sizeof(ifreq));
494 ifreq_set_name(&ifreq, ifp);
495
496 ifreq.ifr_flags = ifp->flags;
497 ifreq.ifr_flags |= flags;
498
499 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
500
501 if (ret < 0) {
502 zlog_info("can't set interface %s(%u) flags %" PRIu64,
503 ifp->name, ifp->vrf->vrf_id, flags);
504 return ret;
505 }
506 return 0;
507 }
508
509 /* Unset interface's flag. */
510 int if_unset_flags(struct interface *ifp, uint64_t flags)
511 {
512 int ret;
513 struct ifreq ifreq;
514
515 memset(&ifreq, 0, sizeof(ifreq));
516 ifreq_set_name(&ifreq, ifp);
517
518 ifreq.ifr_flags = ifp->flags;
519 ifreq.ifr_flags &= ~flags;
520
521 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
522
523 if (ret < 0) {
524 zlog_warn("can't unset interface %s(%u) flags %" PRIu64,
525 ifp->name, ifp->vrf->vrf_id, flags);
526 return ret;
527 }
528 return 0;
529 }
530
531 #ifndef LINUX_IPV6 /* Netlink has its own code */
532
533 #ifdef HAVE_STRUCT_IN6_ALIASREQ
534 #ifndef ND6_INFINITE_LIFETIME
535 #define ND6_INFINITE_LIFETIME 0xffffffffL
536 #endif /* ND6_INFINITE_LIFETIME */
537
538 /*
539 * Helper for interface-addr install, non-netlink
540 */
541 static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
542 {
543 int ret;
544 struct in6_aliasreq addreq;
545 struct sockaddr_in6 addr;
546 struct sockaddr_in6 mask;
547 struct prefix_ipv6 *p;
548
549 p = (struct prefix_ipv6 *)dplane_ctx_get_intf_addr(ctx);
550
551 memset(&addreq, 0, sizeof(addreq));
552 strlcpy((char *)&addreq.ifra_name,
553 dplane_ctx_get_ifname(ctx), sizeof(addreq.ifra_name));
554
555 memset(&addr, 0, sizeof(addr));
556 addr.sin6_addr = p->prefix;
557 addr.sin6_family = p->family;
558 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
559 addr.sin6_len = sizeof(struct sockaddr_in6);
560 #endif
561 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
562
563 memset(&mask, 0, sizeof(mask));
564 masklen2ip6(p->prefixlen, &mask.sin6_addr);
565 mask.sin6_family = p->family;
566 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
567 mask.sin6_len = sizeof(struct sockaddr_in6);
568 #endif
569 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
570
571 addreq.ifra_lifetime.ia6t_vltime = 0xffffffff;
572 addreq.ifra_lifetime.ia6t_pltime = 0xffffffff;
573
574 #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
575 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
576 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
577 #endif
578
579 ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq);
580 if (ret < 0)
581 return ret;
582 return 0;
583 }
584
585 /*
586 * Helper for interface-addr un-install, non-netlink
587 */
588 static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
589 {
590 int ret;
591 struct in6_aliasreq addreq;
592 struct sockaddr_in6 addr;
593 struct sockaddr_in6 mask;
594 struct prefix_ipv6 *p;
595
596 p = (struct prefix_ipv6 *)dplane_ctx_get_intf_addr(ctx);
597
598 memset(&addreq, 0, sizeof(addreq));
599 strlcpy((char *)&addreq.ifra_name,
600 dplane_ctx_get_ifname(ctx), sizeof(addreq.ifra_name));
601
602 memset(&addr, 0, sizeof(addr));
603 addr.sin6_addr = p->prefix;
604 addr.sin6_family = p->family;
605 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
606 addr.sin6_len = sizeof(struct sockaddr_in6);
607 #endif
608 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
609
610 memset(&mask, 0, sizeof(mask));
611 masklen2ip6(p->prefixlen, &mask.sin6_addr);
612 mask.sin6_family = p->family;
613 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
614 mask.sin6_len = sizeof(struct sockaddr_in6);
615 #endif
616 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
617
618 #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
619 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
620 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
621 #endif
622
623 ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq);
624 if (ret < 0)
625 return ret;
626 return 0;
627 }
628 #else
629 /* The old, pre-dataplane code here just returned, so we're retaining that
630 * choice.
631 */
632 static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
633 {
634 return 0;
635 }
636
637 static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx)
638 {
639 return 0;
640 }
641 #endif /* HAVE_STRUCT_IN6_ALIASREQ */
642
643 #endif /* LINUX_IPV6 */