]>
Commit | Line | Data |
---|---|---|
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 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
19 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
20 | * 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <zebra.h> | |
24 | ||
25 | #include "linklist.h" | |
26 | #include "if.h" | |
27 | #include "prefix.h" | |
28 | #include "ioctl.h" | |
29 | #include "log.h" | |
edd7c245 | 30 | #include "privs.h" |
718e3744 | 31 | |
32 | #include "zebra/rib.h" | |
33 | #include "zebra/rt.h" | |
5c78b3d0 | 34 | #include "zebra/interface.h" |
718e3744 | 35 | |
edd7c245 | 36 | extern struct zebra_privs_t zserv_privs; |
37 | ||
718e3744 | 38 | /* clear and set interface name string */ |
39 | void | |
40 | ifreq_set_name (struct ifreq *ifreq, struct interface *ifp) | |
41 | { | |
42 | strncpy (ifreq->ifr_name, ifp->name, IFNAMSIZ); | |
43 | } | |
44 | ||
45 | /* call ioctl system call */ | |
46 | int | |
47 | if_ioctl (u_long request, caddr_t buffer) | |
48 | { | |
49 | int sock; | |
4460e7a4 | 50 | int ret; |
51 | int err; | |
718e3744 | 52 | |
edd7c245 | 53 | if (zserv_privs.change(ZPRIVS_RAISE)) |
54 | zlog (NULL, LOG_ERR, "Can't raise privileges"); | |
718e3744 | 55 | sock = socket (AF_INET, SOCK_DGRAM, 0); |
56 | if (sock < 0) | |
57 | { | |
6a52d0d1 | 58 | int save_errno = errno; |
edd7c245 | 59 | if (zserv_privs.change(ZPRIVS_LOWER)) |
60 | zlog (NULL, LOG_ERR, "Can't lower privileges"); | |
6a52d0d1 | 61 | zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno)); |
718e3744 | 62 | exit (1); |
63 | } | |
4460e7a4 | 64 | if ((ret = ioctl (sock, request, buffer)) < 0) |
65 | err = errno; | |
edd7c245 | 66 | if (zserv_privs.change(ZPRIVS_LOWER)) |
67 | zlog (NULL, LOG_ERR, "Can't lower privileges"); | |
718e3744 | 68 | close (sock); |
69 | ||
70 | if (ret < 0) | |
71 | { | |
72 | errno = err; | |
73 | return ret; | |
74 | } | |
75 | return 0; | |
76 | } | |
77 | ||
78 | #ifdef HAVE_IPV6 | |
a1ac18c4 | 79 | static int |
718e3744 | 80 | if_ioctl_ipv6 (u_long request, caddr_t buffer) |
81 | { | |
82 | int sock; | |
4460e7a4 | 83 | int ret; |
84 | int err; | |
718e3744 | 85 | |
edd7c245 | 86 | if (zserv_privs.change(ZPRIVS_RAISE)) |
87 | zlog (NULL, LOG_ERR, "Can't raise privileges"); | |
718e3744 | 88 | sock = socket (AF_INET6, SOCK_DGRAM, 0); |
89 | if (sock < 0) | |
90 | { | |
6a52d0d1 | 91 | int save_errno = errno; |
edd7c245 | 92 | if (zserv_privs.change(ZPRIVS_LOWER)) |
93 | zlog (NULL, LOG_ERR, "Can't lower privileges"); | |
6a52d0d1 | 94 | zlog_err("Cannot create IPv6 datagram socket: %s", |
95 | safe_strerror(save_errno)); | |
718e3744 | 96 | exit (1); |
97 | } | |
98 | ||
4460e7a4 | 99 | if ((ret = ioctl (sock, request, buffer)) < 0) |
100 | err = errno; | |
edd7c245 | 101 | if (zserv_privs.change(ZPRIVS_LOWER)) |
102 | zlog (NULL, LOG_ERR, "Can't lower privileges"); | |
718e3744 | 103 | close (sock); |
104 | ||
105 | if (ret < 0) | |
106 | { | |
107 | errno = err; | |
108 | return ret; | |
109 | } | |
110 | return 0; | |
111 | } | |
112 | #endif /* HAVE_IPV6 */ | |
113 | ||
114 | /* | |
115 | * get interface metric | |
116 | * -- if value is not avaliable set -1 | |
117 | */ | |
118 | void | |
119 | if_get_metric (struct interface *ifp) | |
120 | { | |
121 | #ifdef SIOCGIFMETRIC | |
122 | struct ifreq ifreq; | |
123 | ||
124 | ifreq_set_name (&ifreq, ifp); | |
125 | ||
126 | if (if_ioctl (SIOCGIFMETRIC, (caddr_t) &ifreq) < 0) | |
127 | return; | |
128 | ifp->metric = ifreq.ifr_metric; | |
129 | if (ifp->metric == 0) | |
130 | ifp->metric = 1; | |
131 | #else /* SIOCGIFMETRIC */ | |
132 | ifp->metric = -1; | |
133 | #endif /* SIOCGIFMETRIC */ | |
134 | } | |
135 | ||
136 | /* get interface MTU */ | |
137 | void | |
138 | if_get_mtu (struct interface *ifp) | |
139 | { | |
140 | struct ifreq ifreq; | |
141 | ||
142 | ifreq_set_name (&ifreq, ifp); | |
143 | ||
144 | #if defined(SIOCGIFMTU) | |
145 | if (if_ioctl (SIOCGIFMTU, (caddr_t) & ifreq) < 0) | |
146 | { | |
147 | zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)"); | |
44145db3 | 148 | ifp->mtu6 = ifp->mtu = -1; |
718e3744 | 149 | return; |
150 | } | |
151 | ||
152 | #ifdef SUNOS_5 | |
44145db3 | 153 | ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; |
718e3744 | 154 | #else |
44145db3 | 155 | ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; |
718e3744 | 156 | #endif /* SUNOS_5 */ |
157 | ||
f5e004f7 PJ |
158 | /* propogate */ |
159 | zebra_interface_up_update(ifp); | |
160 | ||
718e3744 | 161 | #else |
162 | zlog (NULL, LOG_INFO, "Can't lookup mtu on this system"); | |
44145db3 | 163 | ifp->mtu6 = ifp->mtu = -1; |
718e3744 | 164 | #endif |
165 | } | |
166 | ||
167 | #ifdef HAVE_NETLINK | |
168 | /* Interface address setting via netlink interface. */ | |
169 | int | |
170 | if_set_prefix (struct interface *ifp, struct connected *ifc) | |
171 | { | |
172 | return kernel_address_add_ipv4 (ifp, ifc); | |
173 | } | |
174 | ||
175 | /* Interface address is removed using netlink interface. */ | |
176 | int | |
177 | if_unset_prefix (struct interface *ifp, struct connected *ifc) | |
178 | { | |
179 | return kernel_address_delete_ipv4 (ifp, ifc); | |
180 | } | |
181 | #else /* ! HAVE_NETLINK */ | |
6f0e3f6e | 182 | #ifdef HAVE_STRUCT_IFALIASREQ |
718e3744 | 183 | /* Set up interface's IP address, netmask (and broadcas? ). *BSD may |
184 | has ifaliasreq structure. */ | |
185 | int | |
186 | if_set_prefix (struct interface *ifp, struct connected *ifc) | |
187 | { | |
188 | int ret; | |
189 | struct ifaliasreq addreq; | |
190 | struct sockaddr_in addr; | |
191 | struct sockaddr_in mask; | |
192 | struct prefix_ipv4 *p; | |
193 | ||
194 | p = (struct prefix_ipv4 *) ifc->address; | |
195 | ||
196 | memset (&addreq, 0, sizeof addreq); | |
197 | strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); | |
198 | ||
199 | memset (&addr, 0, sizeof (struct sockaddr_in)); | |
200 | addr.sin_addr = p->prefix; | |
201 | addr.sin_family = p->family; | |
6f0e3f6e | 202 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 203 | addr.sin_len = sizeof (struct sockaddr_in); |
204 | #endif | |
205 | memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); | |
206 | ||
207 | memset (&mask, 0, sizeof (struct sockaddr_in)); | |
208 | masklen2ip (p->prefixlen, &mask.sin_addr); | |
209 | mask.sin_family = p->family; | |
6f0e3f6e | 210 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 211 | mask.sin_len = sizeof (struct sockaddr_in); |
212 | #endif | |
213 | memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); | |
214 | ||
215 | ret = if_ioctl (SIOCAIFADDR, (caddr_t) &addreq); | |
216 | if (ret < 0) | |
217 | return ret; | |
218 | return 0; | |
219 | } | |
220 | ||
221 | /* Set up interface's IP address, netmask (and broadcas? ). *BSD may | |
222 | has ifaliasreq structure. */ | |
223 | int | |
224 | if_unset_prefix (struct interface *ifp, struct connected *ifc) | |
225 | { | |
226 | int ret; | |
227 | struct ifaliasreq addreq; | |
228 | struct sockaddr_in addr; | |
229 | struct sockaddr_in mask; | |
230 | struct prefix_ipv4 *p; | |
231 | ||
232 | p = (struct prefix_ipv4 *)ifc->address; | |
233 | ||
234 | memset (&addreq, 0, sizeof addreq); | |
235 | strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); | |
236 | ||
237 | memset (&addr, 0, sizeof (struct sockaddr_in)); | |
238 | addr.sin_addr = p->prefix; | |
239 | addr.sin_family = p->family; | |
6f0e3f6e | 240 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 241 | addr.sin_len = sizeof (struct sockaddr_in); |
242 | #endif | |
243 | memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); | |
244 | ||
245 | memset (&mask, 0, sizeof (struct sockaddr_in)); | |
246 | masklen2ip (p->prefixlen, &mask.sin_addr); | |
247 | mask.sin_family = p->family; | |
6f0e3f6e | 248 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 249 | mask.sin_len = sizeof (struct sockaddr_in); |
250 | #endif | |
251 | memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); | |
252 | ||
253 | ret = if_ioctl (SIOCDIFADDR, (caddr_t) &addreq); | |
254 | if (ret < 0) | |
255 | return ret; | |
256 | return 0; | |
257 | } | |
258 | #else | |
259 | /* Set up interface's address, netmask (and broadcas? ). Linux or | |
260 | Solaris uses ifname:number semantics to set IP address aliases. */ | |
261 | int | |
262 | if_set_prefix (struct interface *ifp, struct connected *ifc) | |
263 | { | |
264 | int ret; | |
265 | struct ifreq ifreq; | |
266 | struct sockaddr_in addr; | |
267 | struct sockaddr_in broad; | |
268 | struct sockaddr_in mask; | |
269 | struct prefix_ipv4 ifaddr; | |
270 | struct prefix_ipv4 *p; | |
271 | ||
272 | p = (struct prefix_ipv4 *) ifc->address; | |
273 | ||
274 | ifaddr = *p; | |
275 | ||
276 | ifreq_set_name (&ifreq, ifp); | |
277 | ||
278 | addr.sin_addr = p->prefix; | |
279 | addr.sin_family = p->family; | |
280 | memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); | |
281 | ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq); | |
282 | if (ret < 0) | |
283 | return ret; | |
284 | ||
285 | /* We need mask for make broadcast addr. */ | |
286 | masklen2ip (p->prefixlen, &mask.sin_addr); | |
287 | ||
288 | if (if_is_broadcast (ifp)) | |
289 | { | |
290 | apply_mask_ipv4 (&ifaddr); | |
291 | addr.sin_addr = ifaddr.prefix; | |
292 | ||
293 | broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); | |
294 | broad.sin_family = p->family; | |
295 | ||
296 | memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in)); | |
297 | ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) &ifreq); | |
298 | if (ret < 0) | |
299 | return ret; | |
300 | } | |
301 | ||
302 | mask.sin_family = p->family; | |
303 | #ifdef SUNOS_5 | |
304 | memcpy (&mask, &ifreq.ifr_addr, sizeof (mask)); | |
305 | #else | |
306 | memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in)); | |
307 | #endif /* SUNOS5 */ | |
308 | ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) &ifreq); | |
309 | if (ret < 0) | |
310 | return ret; | |
311 | ||
312 | return 0; | |
313 | } | |
314 | ||
315 | /* Set up interface's address, netmask (and broadcas? ). Linux or | |
316 | Solaris uses ifname:number semantics to set IP address aliases. */ | |
317 | int | |
318 | if_unset_prefix (struct interface *ifp, struct connected *ifc) | |
319 | { | |
320 | int ret; | |
321 | struct ifreq ifreq; | |
322 | struct sockaddr_in addr; | |
323 | struct prefix_ipv4 *p; | |
324 | ||
325 | p = (struct prefix_ipv4 *) ifc->address; | |
326 | ||
327 | ifreq_set_name (&ifreq, ifp); | |
328 | ||
329 | memset (&addr, 0, sizeof (struct sockaddr_in)); | |
330 | addr.sin_family = p->family; | |
331 | memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); | |
332 | ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq); | |
333 | if (ret < 0) | |
334 | return ret; | |
335 | ||
336 | return 0; | |
337 | } | |
6f0e3f6e | 338 | #endif /* HAVE_STRUCT_IFALIASREQ */ |
718e3744 | 339 | #endif /* HAVE_NETLINK */ |
340 | ||
341 | /* get interface flags */ | |
342 | void | |
343 | if_get_flags (struct interface *ifp) | |
344 | { | |
345 | int ret; | |
346 | struct ifreq ifreq; | |
347 | ||
348 | ifreq_set_name (&ifreq, ifp); | |
349 | ||
350 | ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq); | |
351 | if (ret < 0) | |
352 | { | |
6a52d0d1 | 353 | zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno)); |
718e3744 | 354 | return; |
355 | } | |
356 | ||
5c78b3d0 | 357 | if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff)); |
718e3744 | 358 | } |
359 | ||
360 | /* Set interface flags */ | |
361 | int | |
5c78b3d0 | 362 | if_set_flags (struct interface *ifp, uint64_t flags) |
718e3744 | 363 | { |
364 | int ret; | |
365 | struct ifreq ifreq; | |
366 | ||
d1724b65 | 367 | memset (&ifreq, 0, sizeof(struct ifreq)); |
718e3744 | 368 | ifreq_set_name (&ifreq, ifp); |
369 | ||
370 | ifreq.ifr_flags = ifp->flags; | |
371 | ifreq.ifr_flags |= flags; | |
372 | ||
373 | ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); | |
374 | ||
375 | if (ret < 0) | |
376 | { | |
377 | zlog_info ("can't set interface flags"); | |
378 | return ret; | |
379 | } | |
380 | return 0; | |
381 | } | |
382 | ||
383 | /* Unset interface's flag. */ | |
384 | int | |
5c78b3d0 | 385 | if_unset_flags (struct interface *ifp, uint64_t flags) |
718e3744 | 386 | { |
387 | int ret; | |
388 | struct ifreq ifreq; | |
389 | ||
d1724b65 | 390 | memset (&ifreq, 0, sizeof(struct ifreq)); |
718e3744 | 391 | ifreq_set_name (&ifreq, ifp); |
392 | ||
393 | ifreq.ifr_flags = ifp->flags; | |
394 | ifreq.ifr_flags &= ~flags; | |
395 | ||
396 | ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); | |
397 | ||
398 | if (ret < 0) | |
399 | { | |
400 | zlog_info ("can't unset interface flags"); | |
401 | return ret; | |
402 | } | |
403 | return 0; | |
404 | } | |
405 | ||
406 | #ifdef HAVE_IPV6 | |
407 | ||
408 | #ifdef LINUX_IPV6 | |
409 | #ifndef _LINUX_IN6_H | |
410 | /* linux/include/net/ipv6.h */ | |
411 | struct in6_ifreq | |
412 | { | |
413 | struct in6_addr ifr6_addr; | |
414 | u_int32_t ifr6_prefixlen; | |
415 | int ifr6_ifindex; | |
416 | }; | |
417 | #endif /* _LINUX_IN6_H */ | |
418 | ||
419 | /* Interface's address add/delete functions. */ | |
420 | int | |
421 | if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) | |
422 | { | |
423 | int ret; | |
424 | struct prefix_ipv6 *p; | |
425 | struct in6_ifreq ifreq; | |
426 | ||
427 | p = (struct prefix_ipv6 *) ifc->address; | |
428 | ||
429 | memset (&ifreq, 0, sizeof (struct in6_ifreq)); | |
430 | ||
431 | memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr)); | |
432 | ifreq.ifr6_ifindex = ifp->ifindex; | |
433 | ifreq.ifr6_prefixlen = p->prefixlen; | |
434 | ||
435 | ret = if_ioctl_ipv6 (SIOCSIFADDR, (caddr_t) &ifreq); | |
436 | ||
437 | return ret; | |
438 | } | |
439 | ||
440 | int | |
441 | if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) | |
442 | { | |
443 | int ret; | |
444 | struct prefix_ipv6 *p; | |
445 | struct in6_ifreq ifreq; | |
446 | ||
447 | p = (struct prefix_ipv6 *) ifc->address; | |
448 | ||
449 | memset (&ifreq, 0, sizeof (struct in6_ifreq)); | |
450 | ||
451 | memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr)); | |
452 | ifreq.ifr6_ifindex = ifp->ifindex; | |
453 | ifreq.ifr6_prefixlen = p->prefixlen; | |
454 | ||
455 | ret = if_ioctl_ipv6 (SIOCDIFADDR, (caddr_t) &ifreq); | |
456 | ||
457 | return ret; | |
458 | } | |
459 | #else /* LINUX_IPV6 */ | |
6f0e3f6e | 460 | #ifdef HAVE_STRUCT_IN6_ALIASREQ |
718e3744 | 461 | #ifndef ND6_INFINITE_LIFETIME |
462 | #define ND6_INFINITE_LIFETIME 0xffffffffL | |
463 | #endif /* ND6_INFINITE_LIFETIME */ | |
464 | int | |
465 | if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) | |
466 | { | |
467 | int ret; | |
468 | struct in6_aliasreq addreq; | |
469 | struct sockaddr_in6 addr; | |
470 | struct sockaddr_in6 mask; | |
471 | struct prefix_ipv6 *p; | |
472 | ||
473 | p = (struct prefix_ipv6 * ) ifc->address; | |
474 | ||
475 | memset (&addreq, 0, sizeof addreq); | |
476 | strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); | |
477 | ||
478 | memset (&addr, 0, sizeof (struct sockaddr_in6)); | |
479 | addr.sin6_addr = p->prefix; | |
480 | addr.sin6_family = p->family; | |
6f0e3f6e | 481 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 482 | addr.sin6_len = sizeof (struct sockaddr_in6); |
483 | #endif | |
484 | memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6)); | |
485 | ||
486 | memset (&mask, 0, sizeof (struct sockaddr_in6)); | |
487 | masklen2ip6 (p->prefixlen, &mask.sin6_addr); | |
488 | mask.sin6_family = p->family; | |
6f0e3f6e | 489 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 490 | mask.sin6_len = sizeof (struct sockaddr_in6); |
491 | #endif | |
492 | memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6)); | |
0e4f190e | 493 | |
494 | addreq.ifra_lifetime.ia6t_vltime = 0xffffffff; | |
495 | addreq.ifra_lifetime.ia6t_pltime = 0xffffffff; | |
718e3744 | 496 | |
6f0e3f6e | 497 | #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME |
718e3744 | 498 | addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; |
499 | addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; | |
726f9b2b | 500 | #endif |
718e3744 | 501 | |
502 | ret = if_ioctl_ipv6 (SIOCAIFADDR_IN6, (caddr_t) &addreq); | |
503 | if (ret < 0) | |
504 | return ret; | |
505 | return 0; | |
506 | } | |
507 | ||
508 | int | |
509 | if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) | |
510 | { | |
511 | int ret; | |
512 | struct in6_aliasreq addreq; | |
513 | struct sockaddr_in6 addr; | |
514 | struct sockaddr_in6 mask; | |
515 | struct prefix_ipv6 *p; | |
516 | ||
517 | p = (struct prefix_ipv6 *) ifc->address; | |
518 | ||
519 | memset (&addreq, 0, sizeof addreq); | |
520 | strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); | |
521 | ||
522 | memset (&addr, 0, sizeof (struct sockaddr_in6)); | |
523 | addr.sin6_addr = p->prefix; | |
524 | addr.sin6_family = p->family; | |
6f0e3f6e | 525 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 526 | addr.sin6_len = sizeof (struct sockaddr_in6); |
527 | #endif | |
528 | memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6)); | |
529 | ||
530 | memset (&mask, 0, sizeof (struct sockaddr_in6)); | |
531 | masklen2ip6 (p->prefixlen, &mask.sin6_addr); | |
532 | mask.sin6_family = p->family; | |
6f0e3f6e | 533 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
718e3744 | 534 | mask.sin6_len = sizeof (struct sockaddr_in6); |
535 | #endif | |
536 | memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6)); | |
537 | ||
6f0e3f6e | 538 | #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME |
718e3744 | 539 | addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; |
540 | addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; | |
726f9b2b | 541 | #endif |
718e3744 | 542 | |
543 | ret = if_ioctl_ipv6 (SIOCDIFADDR_IN6, (caddr_t) &addreq); | |
544 | if (ret < 0) | |
545 | return ret; | |
546 | return 0; | |
547 | } | |
548 | #else | |
549 | int | |
550 | if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) | |
551 | { | |
552 | return 0; | |
553 | } | |
554 | ||
555 | int | |
556 | if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) | |
557 | { | |
558 | return 0; | |
559 | } | |
6f0e3f6e | 560 | #endif /* HAVE_STRUCT_IN6_ALIASREQ */ |
718e3744 | 561 | |
562 | #endif /* LINUX_IPV6 */ | |
563 | ||
564 | #endif /* HAVE_IPV6 */ |