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