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