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