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