]> git.proxmox.com Git - mirror_frr.git/blame - zebra/ioctl.c
isisd: implement the 'lsp-too-large' notification
[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 */
c69f2c1f
RZ
418 if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) == -1 &&
419 errno != EINVAL)
450971aa 420 flog_err_sys(EC_LIB_SYSTEM_CALL,
09c866e3
QY
421 "if_ioctl(SIOCGIFMEDIA) failed: %s",
422 safe_strerror(errno));
d62a17ae 423 else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
424 {
425 if (ifmr.ifm_status & IFM_ACTIVE)
426 SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
427 else
428 UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
429 }
430 }
c543a173 431#endif /* HAVE_BSD_LINK_DETECT */
718e3744 432
d62a17ae 433 if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff));
718e3744 434}
435
436/* Set interface flags */
d62a17ae 437int if_set_flags(struct interface *ifp, uint64_t flags)
718e3744 438{
d62a17ae 439 int ret;
440 struct ifreq ifreq;
718e3744 441
d62a17ae 442 memset(&ifreq, 0, sizeof(struct ifreq));
443 ifreq_set_name(&ifreq, ifp);
718e3744 444
d62a17ae 445 ifreq.ifr_flags = ifp->flags;
446 ifreq.ifr_flags |= flags;
718e3744 447
4db21619 448 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
718e3744 449
d62a17ae 450 if (ret < 0) {
451 zlog_info("can't set interface flags");
452 return ret;
453 }
454 return 0;
718e3744 455}
456
457/* Unset interface's flag. */
d62a17ae 458int if_unset_flags(struct interface *ifp, uint64_t flags)
718e3744 459{
d62a17ae 460 int ret;
461 struct ifreq ifreq;
718e3744 462
d62a17ae 463 memset(&ifreq, 0, sizeof(struct ifreq));
464 ifreq_set_name(&ifreq, ifp);
718e3744 465
d62a17ae 466 ifreq.ifr_flags = ifp->flags;
467 ifreq.ifr_flags &= ~flags;
718e3744 468
4db21619 469 ret = vrf_if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq, ifp->vrf_id);
718e3744 470
d62a17ae 471 if (ret < 0) {
472 zlog_info("can't unset interface flags");
473 return ret;
474 }
475 return 0;
718e3744 476}
477
718e3744 478#ifdef LINUX_IPV6
479#ifndef _LINUX_IN6_H
480/* linux/include/net/ipv6.h */
d62a17ae 481struct in6_ifreq {
482 struct in6_addr ifr6_addr;
d7c0a89a 483 uint32_t ifr6_prefixlen;
d62a17ae 484 int ifr6_ifindex;
718e3744 485};
486#endif /* _LINUX_IN6_H */
718e3744 487/* Interface's address add/delete functions. */
d62a17ae 488int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 489{
e86b71f1 490#ifdef HAVE_NETLINK
996c9314 491 return kernel_address_add_ipv6(ifp, ifc);
8aa416a6 492#endif /* HAVE_NETLINK */
718e3744 493}
494
d62a17ae 495int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 496{
e86b71f1 497#ifdef HAVE_NETLINK
996c9314 498 return kernel_address_delete_ipv6(ifp, ifc);
8aa416a6 499#endif /* HAVE_NETLINK */
718e3744 500}
501#else /* LINUX_IPV6 */
6f0e3f6e 502#ifdef HAVE_STRUCT_IN6_ALIASREQ
718e3744 503#ifndef ND6_INFINITE_LIFETIME
504#define ND6_INFINITE_LIFETIME 0xffffffffL
505#endif /* ND6_INFINITE_LIFETIME */
d62a17ae 506int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 507{
d62a17ae 508 int ret;
509 struct in6_aliasreq addreq;
510 struct sockaddr_in6 addr;
511 struct sockaddr_in6 mask;
512 struct prefix_ipv6 *p;
718e3744 513
d62a17ae 514 p = (struct prefix_ipv6 *)ifc->address;
718e3744 515
d62a17ae 516 memset(&addreq, 0, sizeof addreq);
517 strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
718e3744 518
d62a17ae 519 memset(&addr, 0, sizeof(struct sockaddr_in6));
520 addr.sin6_addr = p->prefix;
521 addr.sin6_family = p->family;
6f0e3f6e 522#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 523 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 524#endif
d62a17ae 525 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
718e3744 526
d62a17ae 527 memset(&mask, 0, sizeof(struct sockaddr_in6));
528 masklen2ip6(p->prefixlen, &mask.sin6_addr);
529 mask.sin6_family = p->family;
6f0e3f6e 530#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 531 mask.sin6_len = sizeof(struct sockaddr_in6);
718e3744 532#endif
d62a17ae 533 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
534
535 addreq.ifra_lifetime.ia6t_vltime = 0xffffffff;
536 addreq.ifra_lifetime.ia6t_pltime = 0xffffffff;
537
538#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
539 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
540 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
726f9b2b 541#endif
718e3744 542
d62a17ae 543 ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq);
544 if (ret < 0)
545 return ret;
546 return 0;
718e3744 547}
548
d62a17ae 549int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 550{
d62a17ae 551 int ret;
552 struct in6_aliasreq addreq;
553 struct sockaddr_in6 addr;
554 struct sockaddr_in6 mask;
555 struct prefix_ipv6 *p;
718e3744 556
d62a17ae 557 p = (struct prefix_ipv6 *)ifc->address;
718e3744 558
d62a17ae 559 memset(&addreq, 0, sizeof addreq);
560 strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
718e3744 561
d62a17ae 562 memset(&addr, 0, sizeof(struct sockaddr_in6));
563 addr.sin6_addr = p->prefix;
564 addr.sin6_family = p->family;
6f0e3f6e 565#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 566 addr.sin6_len = sizeof(struct sockaddr_in6);
718e3744 567#endif
d62a17ae 568 memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6));
718e3744 569
d62a17ae 570 memset(&mask, 0, sizeof(struct sockaddr_in6));
571 masklen2ip6(p->prefixlen, &mask.sin6_addr);
572 mask.sin6_family = p->family;
6f0e3f6e 573#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 574 mask.sin6_len = sizeof(struct sockaddr_in6);
718e3744 575#endif
d62a17ae 576 memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6));
718e3744 577
6f0e3f6e 578#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME
d62a17ae 579 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
580 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
726f9b2b 581#endif
718e3744 582
d62a17ae 583 ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq);
584 if (ret < 0)
585 return ret;
586 return 0;
718e3744 587}
588#else
d62a17ae 589int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 590{
d62a17ae 591 return 0;
718e3744 592}
593
d62a17ae 594int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 595{
d62a17ae 596 return 0;
718e3744 597}
6f0e3f6e 598#endif /* HAVE_STRUCT_IN6_ALIASREQ */
718e3744 599
600#endif /* LINUX_IPV6 */
ddfeb486
DL
601
602#endif /* !SUNOS_5 */