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
30 #include "zebra/rib.h"
33 /* clear and set interface name string */
35 ifreq_set_name (struct ifreq *ifreq, struct interface *ifp)
37 strncpy (ifreq->ifr_name, ifp->name, IFNAMSIZ);
40 /* call ioctl system call */
42 if_ioctl (u_long request, caddr_t buffer)
48 sock = socket (AF_INET, SOCK_DGRAM, 0);
55 ret = ioctl (sock, request, buffer);
72 if_ioctl_ipv6 (u_long request, caddr_t buffer)
78 sock = socket (AF_INET6, SOCK_DGRAM, 0);
85 ret = ioctl (sock, request, buffer);
99 #endif /* HAVE_IPV6 */
101 #ifdef BRCM_CMD_SUPPORT
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 #ifdef BRCM_RIP_DEBUG
136 zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)");
143 ifp->mtu = ifreq.ifr_metric;
145 ifp->mtu = ifreq.ifr_mtu;
149 #ifdef BRCM_RIP_DEBUG
150 zlog (NULL, LOG_INFO, "Can't lookup mtu on this system");
155 #endif /* BRCM_CMD_SUPPORT */
158 /* Interface address setting via netlink interface. */
160 if_set_prefix (struct interface *ifp, struct connected *ifc)
162 return kernel_address_add_ipv4 (ifp, ifc);
165 /* Interface address is removed using netlink interface. */
167 if_unset_prefix (struct interface *ifp, struct connected *ifc)
169 return kernel_address_delete_ipv4 (ifp, ifc);
171 #else /* ! HAVE_NETLINK */
172 #ifdef HAVE_IFALIASREQ
173 /* Set up interface's IP address, netmask (and broadcas? ). *BSD may
174 has ifaliasreq structure. */
176 if_set_prefix (struct interface *ifp, struct connected *ifc)
179 struct ifaliasreq addreq;
180 struct sockaddr_in addr;
181 struct sockaddr_in mask;
182 struct prefix_ipv4 *p;
184 p = (struct prefix_ipv4 *) ifc->address;
186 memset (&addreq, 0, sizeof addreq);
187 strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
189 memset (&addr, 0, sizeof (struct sockaddr_in));
190 addr.sin_addr = p->prefix;
191 addr.sin_family = p->family;
193 addr.sin_len = sizeof (struct sockaddr_in);
195 memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
197 memset (&mask, 0, sizeof (struct sockaddr_in));
198 masklen2ip (p->prefixlen, &mask.sin_addr);
199 mask.sin_family = p->family;
201 mask.sin_len = sizeof (struct sockaddr_in);
203 memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
205 ret = if_ioctl (SIOCAIFADDR, (caddr_t) &addreq);
211 /* Set up interface's IP address, netmask (and broadcas? ). *BSD may
212 has ifaliasreq structure. */
214 if_unset_prefix (struct interface *ifp, struct connected *ifc)
217 struct ifaliasreq addreq;
218 struct sockaddr_in addr;
219 struct sockaddr_in mask;
220 struct prefix_ipv4 *p;
222 p = (struct prefix_ipv4 *)ifc->address;
224 memset (&addreq, 0, sizeof addreq);
225 strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
227 memset (&addr, 0, sizeof (struct sockaddr_in));
228 addr.sin_addr = p->prefix;
229 addr.sin_family = p->family;
231 addr.sin_len = sizeof (struct sockaddr_in);
233 memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
235 memset (&mask, 0, sizeof (struct sockaddr_in));
236 masklen2ip (p->prefixlen, &mask.sin_addr);
237 mask.sin_family = p->family;
239 mask.sin_len = sizeof (struct sockaddr_in);
241 memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
243 ret = if_ioctl (SIOCDIFADDR, (caddr_t) &addreq);
249 /* Set up interface's address, netmask (and broadcas? ). Linux or
250 Solaris uses ifname:number semantics to set IP address aliases. */
252 if_set_prefix (struct interface *ifp, struct connected *ifc)
256 struct sockaddr_in addr;
257 struct sockaddr_in broad;
258 struct sockaddr_in mask;
259 struct prefix_ipv4 ifaddr;
260 struct prefix_ipv4 *p;
262 p = (struct prefix_ipv4 *) ifc->address;
266 ifreq_set_name (&ifreq, ifp);
268 addr.sin_addr = p->prefix;
269 addr.sin_family = p->family;
270 memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
271 ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq);
275 /* We need mask for make broadcast addr. */
276 masklen2ip (p->prefixlen, &mask.sin_addr);
278 if (if_is_broadcast (ifp))
280 apply_mask_ipv4 (&ifaddr);
281 addr.sin_addr = ifaddr.prefix;
283 broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
284 broad.sin_family = p->family;
286 memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in));
287 ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) &ifreq);
292 mask.sin_family = p->family;
294 memcpy (&mask, &ifreq.ifr_addr, sizeof (mask));
296 memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in));
298 ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) &ifreq);
305 /* Set up interface's address, netmask (and broadcas? ). Linux or
306 Solaris uses ifname:number semantics to set IP address aliases. */
308 if_unset_prefix (struct interface *ifp, struct connected *ifc)
312 struct sockaddr_in addr;
313 struct prefix_ipv4 *p;
315 p = (struct prefix_ipv4 *) ifc->address;
317 ifreq_set_name (&ifreq, ifp);
319 memset (&addr, 0, sizeof (struct sockaddr_in));
320 addr.sin_family = p->family;
321 memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
322 ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq);
328 #endif /* HAVE_IFALIASREQ */
329 #endif /* HAVE_NETLINK */
331 /* get interface flags */
333 if_get_flags (struct interface *ifp)
338 ifreq_set_name (&ifreq, ifp);
340 ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq);
347 ifp->flags = ifreq.ifr_flags & 0x0000ffff;
350 /* Set interface flags */
352 if_set_flags (struct interface *ifp, unsigned long flags)
357 ifreq_set_name (&ifreq, ifp);
359 ifreq.ifr_flags = ifp->flags;
360 ifreq.ifr_flags |= flags;
362 ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq);
366 #ifdef BRCM_RIP_DEBUG
367 zlog_info ("can't set interface flags");
374 /* Unset interface's flag. */
376 if_unset_flags (struct interface *ifp, unsigned long flags)
381 ifreq_set_name (&ifreq, ifp);
383 ifreq.ifr_flags = ifp->flags;
384 ifreq.ifr_flags &= ~flags;
386 ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq);
390 #ifdef BRCM_RIP_DEBUG
391 zlog_info ("can't unset interface flags");
402 /* linux/include/net/ipv6.h */
405 struct in6_addr ifr6_addr;
406 u_int32_t ifr6_prefixlen;
409 #endif /* _LINUX_IN6_H */
411 /* Interface's address add/delete functions. */
413 if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
416 struct prefix_ipv6 *p;
417 struct in6_ifreq ifreq;
419 p = (struct prefix_ipv6 *) ifc->address;
421 memset (&ifreq, 0, sizeof (struct in6_ifreq));
423 memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr));
424 ifreq.ifr6_ifindex = ifp->ifindex;
425 ifreq.ifr6_prefixlen = p->prefixlen;
427 ret = if_ioctl_ipv6 (SIOCSIFADDR, (caddr_t) &ifreq);
433 if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
436 struct prefix_ipv6 *p;
437 struct in6_ifreq ifreq;
439 p = (struct prefix_ipv6 *) ifc->address;
441 memset (&ifreq, 0, sizeof (struct in6_ifreq));
443 memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr));
444 ifreq.ifr6_ifindex = ifp->ifindex;
445 ifreq.ifr6_prefixlen = p->prefixlen;
447 ret = if_ioctl_ipv6 (SIOCDIFADDR, (caddr_t) &ifreq);
451 #else /* LINUX_IPV6 */
452 #ifdef HAVE_IN6_ALIASREQ
453 #ifndef ND6_INFINITE_LIFETIME
454 #define ND6_INFINITE_LIFETIME 0xffffffffL
455 #endif /* ND6_INFINITE_LIFETIME */
457 if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
460 struct in6_aliasreq addreq;
461 struct sockaddr_in6 addr;
462 struct sockaddr_in6 mask;
463 struct prefix_ipv6 *p;
465 p = (struct prefix_ipv6 * ) ifc->address;
467 memset (&addreq, 0, sizeof addreq);
468 strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
470 memset (&addr, 0, sizeof (struct sockaddr_in6));
471 addr.sin6_addr = p->prefix;
472 addr.sin6_family = p->family;
474 addr.sin6_len = sizeof (struct sockaddr_in6);
476 memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6));
478 memset (&mask, 0, sizeof (struct sockaddr_in6));
479 masklen2ip6 (p->prefixlen, &mask.sin6_addr);
480 mask.sin6_family = p->family;
482 mask.sin6_len = sizeof (struct sockaddr_in6);
484 memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
486 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
487 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
489 ret = if_ioctl_ipv6 (SIOCAIFADDR_IN6, (caddr_t) &addreq);
496 if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
499 struct in6_aliasreq addreq;
500 struct sockaddr_in6 addr;
501 struct sockaddr_in6 mask;
502 struct prefix_ipv6 *p;
504 p = (struct prefix_ipv6 *) ifc->address;
506 memset (&addreq, 0, sizeof addreq);
507 strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name);
509 memset (&addr, 0, sizeof (struct sockaddr_in6));
510 addr.sin6_addr = p->prefix;
511 addr.sin6_family = p->family;
513 addr.sin6_len = sizeof (struct sockaddr_in6);
515 memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6));
517 memset (&mask, 0, sizeof (struct sockaddr_in6));
518 masklen2ip6 (p->prefixlen, &mask.sin6_addr);
519 mask.sin6_family = p->family;
521 mask.sin6_len = sizeof (struct sockaddr_in6);
523 memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6));
525 addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
526 addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
528 ret = if_ioctl_ipv6 (SIOCDIFADDR_IN6, (caddr_t) &addreq);
535 if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
541 if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
545 #endif /* HAVE_IN6_ALIASREQ */
547 #endif /* LINUX_IPV6 */
549 #endif /* HAVE_IPV6 */