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