]> git.proxmox.com Git - mirror_frr.git/blame - zebra/ioctl.c
zebra: dup addr detect clear command
[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
183#ifdef HAVE_NETLINK
184/* Interface address setting via netlink interface. */
d62a17ae 185int if_set_prefix(struct interface *ifp, struct connected *ifc)
718e3744 186{
d62a17ae 187 return kernel_address_add_ipv4(ifp, ifc);
718e3744 188}
189
190/* Interface address is removed using netlink interface. */
d62a17ae 191int if_unset_prefix(struct interface *ifp, struct connected *ifc)
718e3744 192{
d62a17ae 193 return kernel_address_delete_ipv4(ifp, ifc);
718e3744 194}
195#else /* ! HAVE_NETLINK */
6f0e3f6e 196#ifdef HAVE_STRUCT_IFALIASREQ
718e3744 197/* Set up interface's IP address, netmask (and broadcas? ). *BSD may
198 has ifaliasreq structure. */
d62a17ae 199int if_set_prefix(struct interface *ifp, struct connected *ifc)
718e3744 200{
d62a17ae 201 int ret;
202 struct ifaliasreq addreq;
5a41e961 203 struct sockaddr_in addr, mask, peer;
d62a17ae 204 struct prefix_ipv4 *p;
718e3744 205
5a41e961
DL
206 /* don't configure PtP addresses on broadcast ifs or reverse */
207 if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
208 errno = EINVAL;
209 return -1;
210 }
211
d62a17ae 212 p = (struct prefix_ipv4 *)ifc->address;
213 rib_lookup_and_pushup(p, ifp->vrf_id);
718e3744 214
d62a17ae 215 memset(&addreq, 0, sizeof addreq);
216 strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
718e3744 217
d62a17ae 218 memset(&addr, 0, sizeof(struct sockaddr_in));
219 addr.sin_addr = p->prefix;
220 addr.sin_family = p->family;
6f0e3f6e 221#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 222 addr.sin_len = sizeof(struct sockaddr_in);
718e3744 223#endif
d62a17ae 224 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
718e3744 225
5a41e961
DL
226 if (CONNECTED_PEER(ifc)) {
227 p = (struct prefix_ipv4 *)ifc->destination;
228 memset(&mask, 0, sizeof(struct sockaddr_in));
229 peer.sin_addr = p->prefix;
230 peer.sin_family = p->family;
231#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
232 peer.sin_len = sizeof(struct sockaddr_in);
233#endif
234 memcpy(&addreq.ifra_broadaddr, &peer,
235 sizeof(struct sockaddr_in));
236 }
237
d62a17ae 238 memset(&mask, 0, sizeof(struct sockaddr_in));
239 masklen2ip(p->prefixlen, &mask.sin_addr);
240 mask.sin_family = p->family;
6f0e3f6e 241#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 242 mask.sin_len = sizeof(struct sockaddr_in);
718e3744 243#endif
d62a17ae 244 memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
245
246 ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq);
247 if (ret < 0)
248 return ret;
249 return 0;
718e3744 250}
251
252/* Set up interface's IP address, netmask (and broadcas? ). *BSD may
253 has ifaliasreq structure. */
d62a17ae 254int if_unset_prefix(struct interface *ifp, struct connected *ifc)
718e3744 255{
d62a17ae 256 int ret;
257 struct ifaliasreq addreq;
5a41e961 258 struct sockaddr_in addr, mask, peer;
d62a17ae 259 struct prefix_ipv4 *p;
718e3744 260
5a41e961
DL
261 /* this would probably wreak havoc */
262 if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
263 errno = EINVAL;
264 return -1;
265 }
266
d62a17ae 267 p = (struct prefix_ipv4 *)ifc->address;
718e3744 268
d62a17ae 269 memset(&addreq, 0, sizeof addreq);
270 strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
718e3744 271
d62a17ae 272 memset(&addr, 0, sizeof(struct sockaddr_in));
273 addr.sin_addr = p->prefix;
274 addr.sin_family = p->family;
6f0e3f6e 275#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 276 addr.sin_len = sizeof(struct sockaddr_in);
718e3744 277#endif
d62a17ae 278 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
718e3744 279
5a41e961
DL
280 if (CONNECTED_PEER(ifc)) {
281 p = (struct prefix_ipv4 *)ifc->destination;
282 memset(&mask, 0, sizeof(struct sockaddr_in));
283 peer.sin_addr = p->prefix;
284 peer.sin_family = p->family;
285#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
286 peer.sin_len = sizeof(struct sockaddr_in);
287#endif
288 memcpy(&addreq.ifra_broadaddr, &peer,
289 sizeof(struct sockaddr_in));
290 }
291
d62a17ae 292 memset(&mask, 0, sizeof(struct sockaddr_in));
293 masklen2ip(p->prefixlen, &mask.sin_addr);
294 mask.sin_family = p->family;
6f0e3f6e 295#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 296 mask.sin_len = sizeof(struct sockaddr_in);
718e3744 297#endif
d62a17ae 298 memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in));
299
300 ret = if_ioctl(SIOCDIFADDR, (caddr_t)&addreq);
301 if (ret < 0)
302 return ret;
303 return 0;
718e3744 304}
305#else
306/* Set up interface's address, netmask (and broadcas? ). Linux or
307 Solaris uses ifname:number semantics to set IP address aliases. */
d62a17ae 308int if_set_prefix(struct interface *ifp, struct connected *ifc)
718e3744 309{
d62a17ae 310 int ret;
311 struct ifreq ifreq;
312 struct sockaddr_in addr;
313 struct sockaddr_in broad;
314 struct sockaddr_in mask;
315 struct prefix_ipv4 ifaddr;
316 struct prefix_ipv4 *p;
317
318 p = (struct prefix_ipv4 *)ifc->address;
319
320 ifaddr = *p;
321
322 ifreq_set_name(&ifreq, ifp);
323
324 addr.sin_addr = p->prefix;
325 addr.sin_family = p->family;
326 memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
327 ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
328 if (ret < 0)
329 return ret;
330
331 /* We need mask for make broadcast addr. */
332 masklen2ip(p->prefixlen, &mask.sin_addr);
333
334 if (if_is_broadcast(ifp)) {
335 apply_mask_ipv4(&ifaddr);
336 addr.sin_addr = ifaddr.prefix;
337
338 broad.sin_addr.s_addr =
339 (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
340 broad.sin_family = p->family;
341
342 memcpy(&ifreq.ifr_broadaddr, &broad,
343 sizeof(struct sockaddr_in));
344 ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq);
345 if (ret < 0)
346 return ret;
347 }
348
349 mask.sin_family = p->family;
718e3744 350#ifdef SUNOS_5
d62a17ae 351 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask));
718e3744 352#else
d62a17ae 353 memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in));
718e3744 354#endif /* SUNOS5 */
d62a17ae 355 ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq);
356 if (ret < 0)
357 return ret;
718e3744 358
d62a17ae 359 return 0;
718e3744 360}
361
362/* Set up interface's address, netmask (and broadcas? ). Linux or
363 Solaris uses ifname:number semantics to set IP address aliases. */
d62a17ae 364int if_unset_prefix(struct interface *ifp, struct connected *ifc)
718e3744 365{
d62a17ae 366 int ret;
367 struct ifreq ifreq;
368 struct sockaddr_in addr;
369 struct prefix_ipv4 *p;
718e3744 370
d62a17ae 371 p = (struct prefix_ipv4 *)ifc->address;
718e3744 372
d62a17ae 373 ifreq_set_name(&ifreq, ifp);
718e3744 374
d62a17ae 375 memset(&addr, 0, sizeof(struct sockaddr_in));
376 addr.sin_family = p->family;
377 memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
378 ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq);
379 if (ret < 0)
380 return ret;
718e3744 381
d62a17ae 382 return 0;
718e3744 383}
6f0e3f6e 384#endif /* HAVE_STRUCT_IFALIASREQ */
718e3744 385#endif /* HAVE_NETLINK */
386
387/* get interface flags */
d62a17ae 388void if_get_flags(struct interface *ifp)
718e3744 389{
d62a17ae 390 int ret;
391 struct ifreq ifreq;
c543a173 392#ifdef HAVE_BSD_LINK_DETECT
d62a17ae 393 struct ifmediareq ifmr;
c543a173 394#endif /* HAVE_BSD_LINK_DETECT */
718e3744 395
d62a17ae 396 ifreq_set_name(&ifreq, ifp);
718e3744 397
4db21619 398 ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
d62a17ae 399 if (ret < 0) {
450971aa 400 flog_err_sys(EC_LIB_SYSTEM_CALL,
09c866e3
QY
401 "vrf_if_ioctl(SIOCGIFFLAGS) failed: %s",
402 safe_strerror(errno));
d62a17ae 403 return;
404 }
c543a173 405#ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */
0b3f3d47 406
d62a17ae 407 /* Per-default, IFF_RUNNING is held high, unless link-detect says
408 * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag,
409 * following practice on Linux and Solaris kernels
410 */
411 SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
412
413 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
414 (void)memset(&ifmr, 0, sizeof(ifmr));
415 strncpy(ifmr.ifm_name, ifp->name, IFNAMSIZ);
416
417 /* Seems not all interfaces implement this ioctl */
418 if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
450971aa 419 flog_err_sys(EC_LIB_SYSTEM_CALL,
09c866e3
QY
420 "if_ioctl(SIOCGIFMEDIA) failed: %s",
421 safe_strerror(errno));
d62a17ae 422 else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
423 {
424 if (ifmr.ifm_status & IFM_ACTIVE)
425 SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
426 else
427 UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
428 }
429 }
c543a173 430#endif /* HAVE_BSD_LINK_DETECT */
718e3744 431
d62a17ae 432 if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff));
718e3744 433}
434
435/* Set interface flags */
d62a17ae 436int if_set_flags(struct interface *ifp, uint64_t flags)
718e3744 437{
d62a17ae 438 int ret;
439 struct ifreq ifreq;
718e3744 440
d62a17ae 441 memset(&ifreq, 0, sizeof(struct ifreq));
442 ifreq_set_name(&ifreq, ifp);
718e3744 443
d62a17ae 444 ifreq.ifr_flags = ifp->flags;
445 ifreq.ifr_flags |= flags;
718e3744 446
4db21619 447 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
718e3744 448
d62a17ae 449 if (ret < 0) {
450 zlog_info("can't set interface flags");
451 return ret;
452 }
453 return 0;
718e3744 454}
455
456/* Unset interface's flag. */
d62a17ae 457int if_unset_flags(struct interface *ifp, uint64_t flags)
718e3744 458{
d62a17ae 459 int ret;
460 struct ifreq ifreq;
718e3744 461
d62a17ae 462 memset(&ifreq, 0, sizeof(struct ifreq));
463 ifreq_set_name(&ifreq, ifp);
718e3744 464
d62a17ae 465 ifreq.ifr_flags = ifp->flags;
466 ifreq.ifr_flags &= ~flags;
718e3744 467
4db21619 468 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
718e3744 469
d62a17ae 470 if (ret < 0) {
471 zlog_info("can't unset interface flags");
472 return ret;
473 }
474 return 0;
718e3744 475}
476
718e3744 477#ifdef LINUX_IPV6
478#ifndef _LINUX_IN6_H
479/* linux/include/net/ipv6.h */
d62a17ae 480struct in6_ifreq {
481 struct in6_addr ifr6_addr;
d7c0a89a 482 uint32_t ifr6_prefixlen;
d62a17ae 483 int ifr6_ifindex;
718e3744 484};
485#endif /* _LINUX_IN6_H */
718e3744 486/* Interface's address add/delete functions. */
d62a17ae 487int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 488{
e86b71f1 489#ifdef HAVE_NETLINK
996c9314 490 return kernel_address_add_ipv6(ifp, ifc);
8aa416a6 491#endif /* HAVE_NETLINK */
718e3744 492}
493
d62a17ae 494int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 495{
e86b71f1 496#ifdef HAVE_NETLINK
996c9314 497 return kernel_address_delete_ipv6(ifp, ifc);
8aa416a6 498#endif /* HAVE_NETLINK */
718e3744 499}
500#else /* LINUX_IPV6 */
6f0e3f6e 501#ifdef HAVE_STRUCT_IN6_ALIASREQ
718e3744 502#ifndef ND6_INFINITE_LIFETIME
503#define ND6_INFINITE_LIFETIME 0xffffffffL
504#endif /* ND6_INFINITE_LIFETIME */
d62a17ae 505int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 506{
d62a17ae 507 int ret;
508 struct in6_aliasreq addreq;
509 struct sockaddr_in6 addr;
510 struct sockaddr_in6 mask;
511 struct prefix_ipv6 *p;
718e3744 512
d62a17ae 513 p = (struct prefix_ipv6 *)ifc->address;
718e3744 514
d62a17ae 515 memset(&addreq, 0, sizeof addreq);
516 strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
718e3744 517
d62a17ae 518 memset(&addr, 0, sizeof(struct sockaddr_in6));
519 addr.sin6_addr = p->prefix;
520 addr.sin6_family = p->family;
6f0e3f6e 521#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 522 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 523#endif
d62a17ae 524 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
718e3744 525
d62a17ae 526 memset(&mask, 0, sizeof(struct sockaddr_in6));
527 masklen2ip6(p->prefixlen, &mask.sin6_addr);
528 mask.sin6_family = p->family;
6f0e3f6e 529#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 530 mask.sin6_len = sizeof(struct sockaddr_in6);
718e3744 531#endif
d62a17ae 532 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
533
534 addreq.ifra_lifetime.ia6t_vltime = 0xffffffff;
535 addreq.ifra_lifetime.ia6t_pltime = 0xffffffff;
536
537#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
538 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
539 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
726f9b2b 540#endif
718e3744 541
d62a17ae 542 ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq);
543 if (ret < 0)
544 return ret;
545 return 0;
718e3744 546}
547
d62a17ae 548int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 549{
d62a17ae 550 int ret;
551 struct in6_aliasreq addreq;
552 struct sockaddr_in6 addr;
553 struct sockaddr_in6 mask;
554 struct prefix_ipv6 *p;
718e3744 555
d62a17ae 556 p = (struct prefix_ipv6 *)ifc->address;
718e3744 557
d62a17ae 558 memset(&addreq, 0, sizeof addreq);
559 strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
718e3744 560
d62a17ae 561 memset(&addr, 0, sizeof(struct sockaddr_in6));
562 addr.sin6_addr = p->prefix;
563 addr.sin6_family = p->family;
6f0e3f6e 564#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 565 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 566#endif
d62a17ae 567 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
718e3744 568
d62a17ae 569 memset(&mask, 0, sizeof(struct sockaddr_in6));
570 masklen2ip6(p->prefixlen, &mask.sin6_addr);
571 mask.sin6_family = p->family;
6f0e3f6e 572#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 573 mask.sin6_len = sizeof(struct sockaddr_in6);
718e3744 574#endif
d62a17ae 575 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
718e3744 576
6f0e3f6e 577#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
d62a17ae 578 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
579 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
726f9b2b 580#endif
718e3744 581
d62a17ae 582 ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq);
583 if (ret < 0)
584 return ret;
585 return 0;
718e3744 586}
587#else
d62a17ae 588int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 589{
d62a17ae 590 return 0;
718e3744 591}
592
d62a17ae 593int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 594{
d62a17ae 595 return 0;
718e3744 596}
6f0e3f6e 597#endif /* HAVE_STRUCT_IN6_ALIASREQ */
718e3744 598
599#endif /* LINUX_IPV6 */
ddfeb486
DL
600
601#endif /* !SUNOS_5 */