]> git.proxmox.com Git - mirror_frr.git/blame - zebra/ioctl.c
zebra: add 'is broadcast' accessor for interface data
[mirror_frr.git] / zebra / ioctl.c
CommitLineData
718e3744 1/*
2 * Common ioctl functions.
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 "linklist.h"
25#include "if.h"
26#include "prefix.h"
27#include "ioctl.h"
28#include "log.h"
edd7c245 29#include "privs.h"
174482ef 30#include "lib_errors.h"
718e3744 31
5e6a74d8 32#include "vty.h"
718e3744 33#include "zebra/rib.h"
34#include "zebra/rt.h"
5c78b3d0 35#include "zebra/interface.h"
364fed6b 36#include "zebra/zebra_errors.h"
718e3744 37
ddfeb486
DL
38#ifndef SUNOS_5
39
55edb0d4
AS
40#ifdef HAVE_BSD_LINK_DETECT
41#include <net/if_media.h>
42#endif /* HAVE_BSD_LINK_DETECT*/
43
edd7c245 44extern struct zebra_privs_t zserv_privs;
45
718e3744 46/* clear and set interface name string */
d62a17ae 47void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp)
718e3744 48{
0af35d90 49 strlcpy(ifreq->ifr_name, ifp->name, sizeof(ifreq->ifr_name));
718e3744 50}
51
52/* call ioctl system call */
d7c0a89a 53int if_ioctl(unsigned long request, caddr_t buffer)
718e3744 54{
d62a17ae 55 int sock;
56 int ret;
57 int err = 0;
58
01b9e3fd
DL
59 frr_elevate_privs(&zserv_privs) {
60 sock = socket(AF_INET, SOCK_DGRAM, 0);
61 if (sock < 0) {
62 zlog_err("Cannot create UDP socket: %s",
63 safe_strerror(errno));
64 exit(1);
65 }
66 if ((ret = ioctl(sock, request, buffer)) < 0)
67 err = errno;
d62a17ae 68 }
d62a17ae 69 close(sock);
70
71 if (ret < 0) {
72 errno = err;
73 return ret;
74 }
75 return 0;
718e3744 76}
77
4db21619 78/* call ioctl system call */
d7c0a89a 79int vrf_if_ioctl(unsigned long request, caddr_t buffer, vrf_id_t vrf_id)
4db21619
PG
80{
81 int sock;
82 int ret;
83 int err = 0;
84
01b9e3fd
DL
85 frr_elevate_privs(&zserv_privs) {
86 sock = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
87 if (sock < 0) {
88 zlog_err("Cannot create UDP socket: %s",
89 safe_strerror(errno));
90 exit(1);
91 }
92 ret = vrf_ioctl(vrf_id, sock, request, buffer);
93 if (ret < 0)
94 err = errno;
4db21619 95 }
4db21619
PG
96 close(sock);
97
98 if (ret < 0) {
99 errno = err;
100 return ret;
101 }
102 return 0;
103}
104
e86b71f1 105#ifndef HAVE_NETLINK
d7c0a89a 106static int if_ioctl_ipv6(unsigned long request, caddr_t buffer)
718e3744 107{
d62a17ae 108 int sock;
109 int ret;
110 int err = 0;
111
01b9e3fd
DL
112 frr_elevate_privs(&zserv_privs) {
113 sock = socket(AF_INET6, SOCK_DGRAM, 0);
114 if (sock < 0) {
115 zlog_err("Cannot create IPv6 datagram socket: %s",
116 safe_strerror(errno));
117 exit(1);
118 }
d62a17ae 119
01b9e3fd
DL
120 if ((ret = ioctl(sock, request, buffer)) < 0)
121 err = errno;
122 }
d62a17ae 123 close(sock);
124
125 if (ret < 0) {
126 errno = err;
127 return ret;
128 }
129 return 0;
718e3744 130}
e86b71f1 131#endif /* ! HAVE_NETLINK */
718e3744 132
133/*
134 * get interface metric
135 * -- if value is not avaliable set -1
136 */
d62a17ae 137void if_get_metric(struct interface *ifp)
718e3744 138{
139#ifdef SIOCGIFMETRIC
d62a17ae 140 struct ifreq ifreq;
718e3744 141
d62a17ae 142 ifreq_set_name(&ifreq, ifp);
718e3744 143
4db21619 144 if (vrf_if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq, ifp->vrf_id) < 0)
d62a17ae 145 return;
146 ifp->metric = ifreq.ifr_metric;
147 if (ifp->metric == 0)
148 ifp->metric = 1;
149#else /* SIOCGIFMETRIC */
150 ifp->metric = -1;
718e3744 151#endif /* SIOCGIFMETRIC */
152}
153
154/* get interface MTU */
d62a17ae 155void if_get_mtu(struct interface *ifp)
718e3744 156{
d62a17ae 157 struct ifreq ifreq;
718e3744 158
d62a17ae 159 ifreq_set_name(&ifreq, ifp);
718e3744 160
161#if defined(SIOCGIFMTU)
4db21619 162 if (vrf_if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq, ifp->vrf_id) < 0) {
d62a17ae 163 zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU)");
164 ifp->mtu6 = ifp->mtu = -1;
165 return;
166 }
718e3744 167
168#ifdef SUNOS_5
d62a17ae 169 ifp->mtu6 = ifp->mtu = ifreq.ifr_metric;
718e3744 170#else
d62a17ae 171 ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu;
718e3744 172#endif /* SUNOS_5 */
173
d62a17ae 174 /* propogate */
175 zebra_interface_up_update(ifp);
f5e004f7 176
718e3744 177#else
d62a17ae 178 zlog_info("Can't lookup mtu on this system");
179 ifp->mtu6 = ifp->mtu = -1;
718e3744 180#endif
181}
182
64168803
MS
183/*
184 * TODO -- stub handler for interface address programming via the zebra dplane,
185 * for non-netlink platforms.
186 */
187#ifndef HAVE_NETLINK
188
189enum zebra_dplane_result kernel_address_update_ctx(
190 struct zebra_dplane_ctx *ctx)
191{
192 return -1;
193}
194
195#endif /* !HAVE_NETLINK */
196
718e3744 197#ifdef HAVE_NETLINK
198/* Interface address setting via netlink interface. */
d62a17ae 199int if_set_prefix(struct interface *ifp, struct connected *ifc)
718e3744 200{
d62a17ae 201 return kernel_address_add_ipv4(ifp, ifc);
718e3744 202}
203
204/* Interface address is removed using netlink interface. */
d62a17ae 205int if_unset_prefix(struct interface *ifp, struct connected *ifc)
718e3744 206{
d62a17ae 207 return kernel_address_delete_ipv4(ifp, ifc);
718e3744 208}
209#else /* ! HAVE_NETLINK */
6f0e3f6e 210#ifdef HAVE_STRUCT_IFALIASREQ
718e3744 211/* Set up interface's IP address, netmask (and broadcas? ). *BSD may
212 has ifaliasreq structure. */
d62a17ae 213int if_set_prefix(struct interface *ifp, struct connected *ifc)
718e3744 214{
d62a17ae 215 int ret;
216 struct ifaliasreq addreq;
5a41e961 217 struct sockaddr_in addr, mask, peer;
d62a17ae 218 struct prefix_ipv4 *p;
718e3744 219
5a41e961
DL
220 /* don't configure PtP addresses on broadcast ifs or reverse */
221 if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
222 errno = EINVAL;
223 return -1;
224 }
225
d62a17ae 226 p = (struct prefix_ipv4 *)ifc->address;
227 rib_lookup_and_pushup(p, ifp->vrf_id);
718e3744 228
d62a17ae 229 memset(&addreq, 0, sizeof addreq);
138a4965 230 strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
718e3744 231
d62a17ae 232 memset(&addr, 0, sizeof(struct sockaddr_in));
233 addr.sin_addr = p->prefix;
234 addr.sin_family = p->family;
6f0e3f6e 235#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 236 addr.sin_len = sizeof(struct sockaddr_in);
718e3744 237#endif
d62a17ae 238 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
718e3744 239
5a41e961
DL
240 if (CONNECTED_PEER(ifc)) {
241 p = (struct prefix_ipv4 *)ifc->destination;
242 memset(&mask, 0, sizeof(struct sockaddr_in));
243 peer.sin_addr = p->prefix;
244 peer.sin_family = p->family;
245#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
246 peer.sin_len = sizeof(struct sockaddr_in);
247#endif
248 memcpy(&addreq.ifra_broadaddr, &peer,
249 sizeof(struct sockaddr_in));
250 }
251
d62a17ae 252 memset(&mask, 0, sizeof(struct sockaddr_in));
253 masklen2ip(p->prefixlen, &mask.sin_addr);
254 mask.sin_family = p->family;
6f0e3f6e 255#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 256 mask.sin_len = sizeof(struct sockaddr_in);
718e3744 257#endif
d62a17ae 258 memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
259
260 ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq);
261 if (ret < 0)
262 return ret;
263 return 0;
718e3744 264}
265
266/* Set up interface's IP address, netmask (and broadcas? ). *BSD may
267 has ifaliasreq structure. */
d62a17ae 268int if_unset_prefix(struct interface *ifp, struct connected *ifc)
718e3744 269{
d62a17ae 270 int ret;
271 struct ifaliasreq addreq;
5a41e961 272 struct sockaddr_in addr, mask, peer;
d62a17ae 273 struct prefix_ipv4 *p;
718e3744 274
5a41e961
DL
275 /* this would probably wreak havoc */
276 if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
277 errno = EINVAL;
278 return -1;
279 }
280
d62a17ae 281 p = (struct prefix_ipv4 *)ifc->address;
718e3744 282
d62a17ae 283 memset(&addreq, 0, sizeof addreq);
138a4965 284 strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
718e3744 285
d62a17ae 286 memset(&addr, 0, sizeof(struct sockaddr_in));
287 addr.sin_addr = p->prefix;
288 addr.sin_family = p->family;
6f0e3f6e 289#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 290 addr.sin_len = sizeof(struct sockaddr_in);
718e3744 291#endif
d62a17ae 292 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
718e3744 293
5a41e961
DL
294 if (CONNECTED_PEER(ifc)) {
295 p = (struct prefix_ipv4 *)ifc->destination;
296 memset(&mask, 0, sizeof(struct sockaddr_in));
297 peer.sin_addr = p->prefix;
298 peer.sin_family = p->family;
299#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
300 peer.sin_len = sizeof(struct sockaddr_in);
301#endif
302 memcpy(&addreq.ifra_broadaddr, &peer,
303 sizeof(struct sockaddr_in));
304 }
305
d62a17ae 306 memset(&mask, 0, sizeof(struct sockaddr_in));
307 masklen2ip(p->prefixlen, &mask.sin_addr);
308 mask.sin_family = p->family;
6f0e3f6e 309#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 310 mask.sin_len = sizeof(struct sockaddr_in);
718e3744 311#endif
d62a17ae 312 memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
313
314 ret = if_ioctl(SIOCDIFADDR, (caddr_t)&addreq);
315 if (ret < 0)
316 return ret;
317 return 0;
718e3744 318}
319#else
320/* Set up interface's address, netmask (and broadcas? ). Linux or
321 Solaris uses ifname:number semantics to set IP address aliases. */
d62a17ae 322int if_set_prefix(struct interface *ifp, struct connected *ifc)
718e3744 323{
d62a17ae 324 int ret;
325 struct ifreq ifreq;
326 struct sockaddr_in addr;
327 struct sockaddr_in broad;
328 struct sockaddr_in mask;
329 struct prefix_ipv4 ifaddr;
330 struct prefix_ipv4 *p;
331
332 p = (struct prefix_ipv4 *)ifc->address;
333
334 ifaddr = *p;
335
336 ifreq_set_name(&ifreq, ifp);
337
338 addr.sin_addr = p->prefix;
339 addr.sin_family = p->family;
340 memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
341 ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
342 if (ret < 0)
343 return ret;
344
345 /* We need mask for make broadcast addr. */
346 masklen2ip(p->prefixlen, &mask.sin_addr);
347
348 if (if_is_broadcast(ifp)) {
349 apply_mask_ipv4(&ifaddr);
350 addr.sin_addr = ifaddr.prefix;
351
352 broad.sin_addr.s_addr =
353 (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
354 broad.sin_family = p->family;
355
356 memcpy(&ifreq.ifr_broadaddr, &broad,
357 sizeof(struct sockaddr_in));
358 ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq);
359 if (ret < 0)
360 return ret;
361 }
362
363 mask.sin_family = p->family;
718e3744 364#ifdef SUNOS_5
d62a17ae 365 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask));
718e3744 366#else
d62a17ae 367 memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in));
718e3744 368#endif /* SUNOS5 */
d62a17ae 369 ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq);
370 if (ret < 0)
371 return ret;
718e3744 372
d62a17ae 373 return 0;
718e3744 374}
375
376/* Set up interface's address, netmask (and broadcas? ). Linux or
377 Solaris uses ifname:number semantics to set IP address aliases. */
d62a17ae 378int if_unset_prefix(struct interface *ifp, struct connected *ifc)
718e3744 379{
d62a17ae 380 int ret;
381 struct ifreq ifreq;
382 struct sockaddr_in addr;
383 struct prefix_ipv4 *p;
718e3744 384
d62a17ae 385 p = (struct prefix_ipv4 *)ifc->address;
718e3744 386
d62a17ae 387 ifreq_set_name(&ifreq, ifp);
718e3744 388
d62a17ae 389 memset(&addr, 0, sizeof(struct sockaddr_in));
390 addr.sin_family = p->family;
391 memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
392 ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
393 if (ret < 0)
394 return ret;
718e3744 395
d62a17ae 396 return 0;
718e3744 397}
6f0e3f6e 398#endif /* HAVE_STRUCT_IFALIASREQ */
718e3744 399#endif /* HAVE_NETLINK */
400
401/* get interface flags */
d62a17ae 402void if_get_flags(struct interface *ifp)
718e3744 403{
d62a17ae 404 int ret;
405 struct ifreq ifreq;
c543a173 406#ifdef HAVE_BSD_LINK_DETECT
d62a17ae 407 struct ifmediareq ifmr;
c543a173 408#endif /* HAVE_BSD_LINK_DETECT */
718e3744 409
d62a17ae 410 ifreq_set_name(&ifreq, ifp);
718e3744 411
4db21619 412 ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
d62a17ae 413 if (ret < 0) {
450971aa 414 flog_err_sys(EC_LIB_SYSTEM_CALL,
09c866e3
QY
415 "vrf_if_ioctl(SIOCGIFFLAGS) failed: %s",
416 safe_strerror(errno));
d62a17ae 417 return;
418 }
c543a173 419#ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */
0b3f3d47 420
d62a17ae 421 /* Per-default, IFF_RUNNING is held high, unless link-detect says
422 * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag,
423 * following practice on Linux and Solaris kernels
424 */
425 SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
426
427 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
428 (void)memset(&ifmr, 0, sizeof(ifmr));
138a4965 429 strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
d62a17ae 430
431 /* Seems not all interfaces implement this ioctl */
c69f2c1f
RZ
432 if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) == -1 &&
433 errno != EINVAL)
450971aa 434 flog_err_sys(EC_LIB_SYSTEM_CALL,
09c866e3
QY
435 "if_ioctl(SIOCGIFMEDIA) failed: %s",
436 safe_strerror(errno));
d62a17ae 437 else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
438 {
439 if (ifmr.ifm_status & IFM_ACTIVE)
440 SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
441 else
442 UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
443 }
444 }
c543a173 445#endif /* HAVE_BSD_LINK_DETECT */
718e3744 446
d62a17ae 447 if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff));
718e3744 448}
449
450/* Set interface flags */
d62a17ae 451int if_set_flags(struct interface *ifp, uint64_t flags)
718e3744 452{
d62a17ae 453 int ret;
454 struct ifreq ifreq;
718e3744 455
d62a17ae 456 memset(&ifreq, 0, sizeof(struct ifreq));
457 ifreq_set_name(&ifreq, ifp);
718e3744 458
d62a17ae 459 ifreq.ifr_flags = ifp->flags;
460 ifreq.ifr_flags |= flags;
718e3744 461
4db21619 462 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
718e3744 463
d62a17ae 464 if (ret < 0) {
465 zlog_info("can't set interface flags");
466 return ret;
467 }
468 return 0;
718e3744 469}
470
471/* Unset interface's flag. */
d62a17ae 472int if_unset_flags(struct interface *ifp, uint64_t flags)
718e3744 473{
d62a17ae 474 int ret;
475 struct ifreq ifreq;
718e3744 476
d62a17ae 477 memset(&ifreq, 0, sizeof(struct ifreq));
478 ifreq_set_name(&ifreq, ifp);
718e3744 479
d62a17ae 480 ifreq.ifr_flags = ifp->flags;
481 ifreq.ifr_flags &= ~flags;
718e3744 482
4db21619 483 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
718e3744 484
d62a17ae 485 if (ret < 0) {
486 zlog_info("can't unset interface flags");
487 return ret;
488 }
489 return 0;
718e3744 490}
491
718e3744 492#ifdef LINUX_IPV6
493#ifndef _LINUX_IN6_H
494/* linux/include/net/ipv6.h */
d62a17ae 495struct in6_ifreq {
496 struct in6_addr ifr6_addr;
d7c0a89a 497 uint32_t ifr6_prefixlen;
d62a17ae 498 int ifr6_ifindex;
718e3744 499};
500#endif /* _LINUX_IN6_H */
718e3744 501/* Interface's address add/delete functions. */
d62a17ae 502int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 503{
e86b71f1 504#ifdef HAVE_NETLINK
996c9314 505 return kernel_address_add_ipv6(ifp, ifc);
8aa416a6 506#endif /* HAVE_NETLINK */
718e3744 507}
508
d62a17ae 509int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 510{
e86b71f1 511#ifdef HAVE_NETLINK
996c9314 512 return kernel_address_delete_ipv6(ifp, ifc);
8aa416a6 513#endif /* HAVE_NETLINK */
718e3744 514}
515#else /* LINUX_IPV6 */
6f0e3f6e 516#ifdef HAVE_STRUCT_IN6_ALIASREQ
718e3744 517#ifndef ND6_INFINITE_LIFETIME
518#define ND6_INFINITE_LIFETIME 0xffffffffL
519#endif /* ND6_INFINITE_LIFETIME */
d62a17ae 520int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 521{
d62a17ae 522 int ret;
523 struct in6_aliasreq addreq;
524 struct sockaddr_in6 addr;
525 struct sockaddr_in6 mask;
526 struct prefix_ipv6 *p;
718e3744 527
d62a17ae 528 p = (struct prefix_ipv6 *)ifc->address;
718e3744 529
d62a17ae 530 memset(&addreq, 0, sizeof addreq);
138a4965 531 strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
718e3744 532
d62a17ae 533 memset(&addr, 0, sizeof(struct sockaddr_in6));
534 addr.sin6_addr = p->prefix;
535 addr.sin6_family = p->family;
6f0e3f6e 536#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 537 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 538#endif
d62a17ae 539 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
718e3744 540
d62a17ae 541 memset(&mask, 0, sizeof(struct sockaddr_in6));
542 masklen2ip6(p->prefixlen, &mask.sin6_addr);
543 mask.sin6_family = p->family;
6f0e3f6e 544#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 545 mask.sin6_len = sizeof(struct sockaddr_in6);
718e3744 546#endif
d62a17ae 547 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
548
549 addreq.ifra_lifetime.ia6t_vltime = 0xffffffff;
550 addreq.ifra_lifetime.ia6t_pltime = 0xffffffff;
551
552#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
553 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
554 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
726f9b2b 555#endif
718e3744 556
d62a17ae 557 ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq);
558 if (ret < 0)
559 return ret;
560 return 0;
718e3744 561}
562
d62a17ae 563int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 564{
d62a17ae 565 int ret;
566 struct in6_aliasreq addreq;
567 struct sockaddr_in6 addr;
568 struct sockaddr_in6 mask;
569 struct prefix_ipv6 *p;
718e3744 570
d62a17ae 571 p = (struct prefix_ipv6 *)ifc->address;
718e3744 572
d62a17ae 573 memset(&addreq, 0, sizeof addreq);
138a4965 574 strlcpy(addreq.ifra_name, ifp->name, sizeof(addreq.ifra_name));
718e3744 575
d62a17ae 576 memset(&addr, 0, sizeof(struct sockaddr_in6));
577 addr.sin6_addr = p->prefix;
578 addr.sin6_family = p->family;
6f0e3f6e 579#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 580 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 581#endif
d62a17ae 582 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
718e3744 583
d62a17ae 584 memset(&mask, 0, sizeof(struct sockaddr_in6));
585 masklen2ip6(p->prefixlen, &mask.sin6_addr);
586 mask.sin6_family = p->family;
6f0e3f6e 587#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 588 mask.sin6_len = sizeof(struct sockaddr_in6);
718e3744 589#endif
d62a17ae 590 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
718e3744 591
6f0e3f6e 592#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
d62a17ae 593 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
594 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
726f9b2b 595#endif
718e3744 596
d62a17ae 597 ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq);
598 if (ret < 0)
599 return ret;
600 return 0;
718e3744 601}
602#else
d62a17ae 603int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 604{
d62a17ae 605 return 0;
718e3744 606}
607
d62a17ae 608int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 609{
d62a17ae 610 return 0;
718e3744 611}
6f0e3f6e 612#endif /* HAVE_STRUCT_IN6_ALIASREQ */
718e3744 613
614#endif /* LINUX_IPV6 */
ddfeb486
DL
615
616#endif /* !SUNOS_5 */