]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/ioctl.c
2 * Common ioctl functions.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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
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.
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
31 #include "zebra/rib.h"
34 /* clear and set interface name string */
36 ifreq_set_name (struct ifreq
*ifreq
, struct interface
*ifp
)
38 strncpy (ifreq
->ifr_name
, ifp
->name
, IFNAMSIZ
);
41 /* call ioctl system call */
43 if_ioctl (u_long request
, caddr_t buffer
)
49 sock
= socket (AF_INET
, SOCK_DGRAM
, 0);
56 ret
= ioctl (sock
, request
, buffer
);
73 if_ioctl_ipv6 (u_long request
, caddr_t buffer
)
79 sock
= socket (AF_INET6
, SOCK_DGRAM
, 0);
86 ret
= ioctl (sock
, request
, buffer
);
100 #endif /* HAVE_IPV6 */
103 * get interface metric
104 * -- if value is not avaliable set -1
107 if_get_metric (struct interface
*ifp
)
112 ifreq_set_name (&ifreq
, ifp
);
114 if (if_ioctl (SIOCGIFMETRIC
, (caddr_t
) &ifreq
) < 0)
116 ifp
->metric
= ifreq
.ifr_metric
;
117 if (ifp
->metric
== 0)
119 #else /* SIOCGIFMETRIC */
121 #endif /* SIOCGIFMETRIC */
124 /* get interface MTU */
126 if_get_mtu (struct interface
*ifp
)
130 ifreq_set_name (&ifreq
, ifp
);
132 #if defined(SIOCGIFMTU)
133 if (if_ioctl (SIOCGIFMTU
, (caddr_t
) & ifreq
) < 0)
135 zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)");
141 ifp
->mtu
= ifreq
.ifr_metric
;
143 ifp
->mtu
= ifreq
.ifr_mtu
;
147 zlog (NULL
, LOG_INFO
, "Can't lookup mtu on this system");
153 /* Interface address setting via netlink interface. */
155 if_set_prefix (struct interface
*ifp
, struct connected
*ifc
)
157 return kernel_address_add_ipv4 (ifp
, ifc
);
160 /* Interface address is removed using netlink interface. */
162 if_unset_prefix (struct interface
*ifp
, struct connected
*ifc
)
164 return kernel_address_delete_ipv4 (ifp
, ifc
);
166 #else /* ! HAVE_NETLINK */
167 #ifdef HAVE_IFALIASREQ
168 /* Set up interface's IP address, netmask (and broadcas? ). *BSD may
169 has ifaliasreq structure. */
171 if_set_prefix (struct interface
*ifp
, struct connected
*ifc
)
174 struct ifaliasreq addreq
;
175 struct sockaddr_in addr
;
176 struct sockaddr_in mask
;
177 struct prefix_ipv4
*p
;
179 p
= (struct prefix_ipv4
*) ifc
->address
;
181 memset (&addreq
, 0, sizeof addreq
);
182 strncpy ((char *)&addreq
.ifra_name
, ifp
->name
, sizeof addreq
.ifra_name
);
184 memset (&addr
, 0, sizeof (struct sockaddr_in
));
185 addr
.sin_addr
= p
->prefix
;
186 addr
.sin_family
= p
->family
;
188 addr
.sin_len
= sizeof (struct sockaddr_in
);
190 memcpy (&addreq
.ifra_addr
, &addr
, sizeof (struct sockaddr_in
));
192 memset (&mask
, 0, sizeof (struct sockaddr_in
));
193 masklen2ip (p
->prefixlen
, &mask
.sin_addr
);
194 mask
.sin_family
= p
->family
;
196 mask
.sin_len
= sizeof (struct sockaddr_in
);
198 memcpy (&addreq
.ifra_mask
, &mask
, sizeof (struct sockaddr_in
));
200 ret
= if_ioctl (SIOCAIFADDR
, (caddr_t
) &addreq
);
206 /* Set up interface's IP address, netmask (and broadcas? ). *BSD may
207 has ifaliasreq structure. */
209 if_unset_prefix (struct interface
*ifp
, struct connected
*ifc
)
212 struct ifaliasreq addreq
;
213 struct sockaddr_in addr
;
214 struct sockaddr_in mask
;
215 struct prefix_ipv4
*p
;
217 p
= (struct prefix_ipv4
*)ifc
->address
;
219 memset (&addreq
, 0, sizeof addreq
);
220 strncpy ((char *)&addreq
.ifra_name
, ifp
->name
, sizeof addreq
.ifra_name
);
222 memset (&addr
, 0, sizeof (struct sockaddr_in
));
223 addr
.sin_addr
= p
->prefix
;
224 addr
.sin_family
= p
->family
;
226 addr
.sin_len
= sizeof (struct sockaddr_in
);
228 memcpy (&addreq
.ifra_addr
, &addr
, sizeof (struct sockaddr_in
));
230 memset (&mask
, 0, sizeof (struct sockaddr_in
));
231 masklen2ip (p
->prefixlen
, &mask
.sin_addr
);
232 mask
.sin_family
= p
->family
;
234 mask
.sin_len
= sizeof (struct sockaddr_in
);
236 memcpy (&addreq
.ifra_mask
, &mask
, sizeof (struct sockaddr_in
));
238 ret
= if_ioctl (SIOCDIFADDR
, (caddr_t
) &addreq
);
244 /* Set up interface's address, netmask (and broadcas? ). Linux or
245 Solaris uses ifname:number semantics to set IP address aliases. */
247 if_set_prefix (struct interface
*ifp
, struct connected
*ifc
)
251 struct sockaddr_in addr
;
252 struct sockaddr_in broad
;
253 struct sockaddr_in mask
;
254 struct prefix_ipv4 ifaddr
;
255 struct prefix_ipv4
*p
;
257 p
= (struct prefix_ipv4
*) ifc
->address
;
261 ifreq_set_name (&ifreq
, ifp
);
263 addr
.sin_addr
= p
->prefix
;
264 addr
.sin_family
= p
->family
;
265 memcpy (&ifreq
.ifr_addr
, &addr
, sizeof (struct sockaddr_in
));
266 ret
= if_ioctl (SIOCSIFADDR
, (caddr_t
) &ifreq
);
270 /* We need mask for make broadcast addr. */
271 masklen2ip (p
->prefixlen
, &mask
.sin_addr
);
273 if (if_is_broadcast (ifp
))
275 apply_mask_ipv4 (&ifaddr
);
276 addr
.sin_addr
= ifaddr
.prefix
;
278 broad
.sin_addr
.s_addr
= (addr
.sin_addr
.s_addr
| ~mask
.sin_addr
.s_addr
);
279 broad
.sin_family
= p
->family
;
281 memcpy (&ifreq
.ifr_broadaddr
, &broad
, sizeof (struct sockaddr_in
));
282 ret
= if_ioctl (SIOCSIFBRDADDR
, (caddr_t
) &ifreq
);
287 mask
.sin_family
= p
->family
;
289 memcpy (&mask
, &ifreq
.ifr_addr
, sizeof (mask
));
291 memcpy (&ifreq
.ifr_netmask
, &mask
, sizeof (struct sockaddr_in
));
293 ret
= if_ioctl (SIOCSIFNETMASK
, (caddr_t
) &ifreq
);
300 /* Set up interface's address, netmask (and broadcas? ). Linux or
301 Solaris uses ifname:number semantics to set IP address aliases. */
303 if_unset_prefix (struct interface
*ifp
, struct connected
*ifc
)
307 struct sockaddr_in addr
;
308 struct prefix_ipv4
*p
;
310 p
= (struct prefix_ipv4
*) ifc
->address
;
312 ifreq_set_name (&ifreq
, ifp
);
314 memset (&addr
, 0, sizeof (struct sockaddr_in
));
315 addr
.sin_family
= p
->family
;
316 memcpy (&ifreq
.ifr_addr
, &addr
, sizeof (struct sockaddr_in
));
317 ret
= if_ioctl (SIOCSIFADDR
, (caddr_t
) &ifreq
);
323 #endif /* HAVE_IFALIASREQ */
324 #endif /* HAVE_NETLINK */
326 /* get interface flags */
328 if_get_flags (struct interface
*ifp
)
333 ifreq_set_name (&ifreq
, ifp
);
335 ret
= if_ioctl (SIOCGIFFLAGS
, (caddr_t
) &ifreq
);
342 ifp
->flags
= ifreq
.ifr_flags
& 0x0000ffff;
345 /* Set interface flags */
347 if_set_flags (struct interface
*ifp
, unsigned long flags
)
352 ifreq_set_name (&ifreq
, ifp
);
354 ifreq
.ifr_flags
= ifp
->flags
;
355 ifreq
.ifr_flags
|= flags
;
357 ret
= if_ioctl (SIOCSIFFLAGS
, (caddr_t
) &ifreq
);
361 zlog_info ("can't set interface flags");
367 /* Unset interface's flag. */
369 if_unset_flags (struct interface
*ifp
, unsigned long flags
)
374 ifreq_set_name (&ifreq
, ifp
);
376 ifreq
.ifr_flags
= ifp
->flags
;
377 ifreq
.ifr_flags
&= ~flags
;
379 ret
= if_ioctl (SIOCSIFFLAGS
, (caddr_t
) &ifreq
);
383 zlog_info ("can't unset interface flags");
393 /* linux/include/net/ipv6.h */
396 struct in6_addr ifr6_addr
;
397 u_int32_t ifr6_prefixlen
;
400 #endif /* _LINUX_IN6_H */
402 /* Interface's address add/delete functions. */
404 if_prefix_add_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
407 struct prefix_ipv6
*p
;
408 struct in6_ifreq ifreq
;
410 p
= (struct prefix_ipv6
*) ifc
->address
;
412 memset (&ifreq
, 0, sizeof (struct in6_ifreq
));
414 memcpy (&ifreq
.ifr6_addr
, &p
->prefix
, sizeof (struct in6_addr
));
415 ifreq
.ifr6_ifindex
= ifp
->ifindex
;
416 ifreq
.ifr6_prefixlen
= p
->prefixlen
;
418 ret
= if_ioctl_ipv6 (SIOCSIFADDR
, (caddr_t
) &ifreq
);
424 if_prefix_delete_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
427 struct prefix_ipv6
*p
;
428 struct in6_ifreq ifreq
;
430 p
= (struct prefix_ipv6
*) ifc
->address
;
432 memset (&ifreq
, 0, sizeof (struct in6_ifreq
));
434 memcpy (&ifreq
.ifr6_addr
, &p
->prefix
, sizeof (struct in6_addr
));
435 ifreq
.ifr6_ifindex
= ifp
->ifindex
;
436 ifreq
.ifr6_prefixlen
= p
->prefixlen
;
438 ret
= if_ioctl_ipv6 (SIOCDIFADDR
, (caddr_t
) &ifreq
);
442 #else /* LINUX_IPV6 */
443 #ifdef HAVE_IN6_ALIASREQ
444 #ifndef ND6_INFINITE_LIFETIME
445 #define ND6_INFINITE_LIFETIME 0xffffffffL
446 #endif /* ND6_INFINITE_LIFETIME */
448 if_prefix_add_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
451 struct in6_aliasreq addreq
;
452 struct sockaddr_in6 addr
;
453 struct sockaddr_in6 mask
;
454 struct prefix_ipv6
*p
;
456 p
= (struct prefix_ipv6
* ) ifc
->address
;
458 memset (&addreq
, 0, sizeof addreq
);
459 strncpy ((char *)&addreq
.ifra_name
, ifp
->name
, sizeof addreq
.ifra_name
);
461 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
462 addr
.sin6_addr
= p
->prefix
;
463 addr
.sin6_family
= p
->family
;
465 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
467 memcpy (&addreq
.ifra_addr
, &addr
, sizeof (struct sockaddr_in6
));
469 memset (&mask
, 0, sizeof (struct sockaddr_in6
));
470 masklen2ip6 (p
->prefixlen
, &mask
.sin6_addr
);
471 mask
.sin6_family
= p
->family
;
473 mask
.sin6_len
= sizeof (struct sockaddr_in6
);
475 memcpy (&addreq
.ifra_prefixmask
, &mask
, sizeof (struct sockaddr_in6
));
477 addreq
.ifra_lifetime
.ia6t_pltime
= ND6_INFINITE_LIFETIME
;
478 addreq
.ifra_lifetime
.ia6t_vltime
= ND6_INFINITE_LIFETIME
;
480 ret
= if_ioctl_ipv6 (SIOCAIFADDR_IN6
, (caddr_t
) &addreq
);
487 if_prefix_delete_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
490 struct in6_aliasreq addreq
;
491 struct sockaddr_in6 addr
;
492 struct sockaddr_in6 mask
;
493 struct prefix_ipv6
*p
;
495 p
= (struct prefix_ipv6
*) ifc
->address
;
497 memset (&addreq
, 0, sizeof addreq
);
498 strncpy ((char *)&addreq
.ifra_name
, ifp
->name
, sizeof addreq
.ifra_name
);
500 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
501 addr
.sin6_addr
= p
->prefix
;
502 addr
.sin6_family
= p
->family
;
504 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
506 memcpy (&addreq
.ifra_addr
, &addr
, sizeof (struct sockaddr_in6
));
508 memset (&mask
, 0, sizeof (struct sockaddr_in6
));
509 masklen2ip6 (p
->prefixlen
, &mask
.sin6_addr
);
510 mask
.sin6_family
= p
->family
;
512 mask
.sin6_len
= sizeof (struct sockaddr_in6
);
514 memcpy (&addreq
.ifra_prefixmask
, &mask
, sizeof (struct sockaddr_in6
));
516 addreq
.ifra_lifetime
.ia6t_pltime
= ND6_INFINITE_LIFETIME
;
517 addreq
.ifra_lifetime
.ia6t_vltime
= ND6_INFINITE_LIFETIME
;
519 ret
= if_ioctl_ipv6 (SIOCDIFADDR_IN6
, (caddr_t
) &addreq
);
526 if_prefix_add_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
532 if_prefix_delete_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
536 #endif /* HAVE_IN6_ALIASREQ */
538 #endif /* LINUX_IPV6 */
540 #endif /* HAVE_IPV6 */