|
|
@ -126,112 +126,110 @@ int iface_enumerate(int family, void *parm, callback_t callback)
|
|
|
|
|
|
|
|
|
|
|
|
for (addrs = head; addrs; addrs = addrs->ifa_next)
|
|
|
|
for (addrs = head; addrs; addrs = addrs->ifa_next)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (addrs->ifa_addr->sa_family == family)
|
|
|
|
int iface_index = if_nametoindex(addrs->ifa_name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (iface_index == 0 || !addrs->ifa_addr ||
|
|
|
|
|
|
|
|
addrs->ifa_addr->sa_family != family ||
|
|
|
|
|
|
|
|
(!addrs->ifa_netmask && family != AF_LINK))
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (family == AF_INET)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int iface_index = if_nametoindex(addrs->ifa_name);
|
|
|
|
struct in_addr addr, netmask, broadcast;
|
|
|
|
|
|
|
|
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
|
|
|
if (iface_index == 0 || !addrs->ifa_addr ||
|
|
|
|
|
|
|
|
(!addrs->ifa_netmask && family != AF_LINK))
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (family == AF_INET)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct in_addr addr, netmask, broadcast;
|
|
|
|
|
|
|
|
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
|
|
|
|
|
|
|
#ifdef HAVE_BSD_NETWORK
|
|
|
|
#ifdef HAVE_BSD_NETWORK
|
|
|
|
if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr)
|
|
|
|
if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
|
|
|
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
|
|
|
if (addrs->ifa_broadaddr)
|
|
|
|
if (addrs->ifa_broadaddr)
|
|
|
|
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
|
|
|
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
broadcast.s_addr = 0;
|
|
|
|
broadcast.s_addr = 0;
|
|
|
|
if (!callback.af_inet(addr, iface_index, NULL, netmask, broadcast, parm))
|
|
|
|
if (!callback.af_inet(addr, iface_index, NULL, netmask, broadcast, parm))
|
|
|
|
goto err;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (family == AF_INET6)
|
|
|
|
else if (family == AF_INET6)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
|
|
|
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
|
|
|
unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
|
|
|
|
unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
|
|
|
|
int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
|
|
|
|
int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
|
|
|
|
int i, j, prefix = 0;
|
|
|
|
int i, j, prefix = 0;
|
|
|
|
u32 valid = 0xffffffff, preferred = 0xffffffff;
|
|
|
|
u32 valid = 0xffffffff, preferred = 0xffffffff;
|
|
|
|
int flags = 0;
|
|
|
|
int flags = 0;
|
|
|
|
#ifdef HAVE_BSD_NETWORK
|
|
|
|
#ifdef HAVE_BSD_NETWORK
|
|
|
|
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr))
|
|
|
|
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
|
|
|
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
|
|
|
struct in6_ifreq ifr6;
|
|
|
|
struct in6_ifreq ifr6;
|
|
|
|
|
|
|
|
|
|
|
|
memset(&ifr6, 0, sizeof(ifr6));
|
|
|
|
memset(&ifr6, 0, sizeof(ifr6));
|
|
|
|
safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
|
|
|
safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
|
|
|
|
|
|
|
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
|
|
|
|
|
|
|
|
flags |= IFACE_TENTATIVE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
|
|
|
|
|
|
|
|
flags |= IFACE_DEPRECATED;
|
|
|
|
|
|
|
|
|
|
|
|
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
|
|
|
|
|
|
|
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
|
|
|
|
|
|
|
|
flags |= IFACE_TENTATIVE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
|
|
|
|
|
|
|
|
flags |= IFACE_DEPRECATED;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef IN6_IFF_TEMPORARY
|
|
|
|
#ifdef IN6_IFF_TEMPORARY
|
|
|
|
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
|
|
|
|
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
|
|
|
|
flags |= IFACE_PERMANENT;
|
|
|
|
flags |= IFACE_PERMANENT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef IN6_IFF_PRIVACY
|
|
|
|
|
|
|
|
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
|
|
|
|
|
|
|
|
flags |= IFACE_PERMANENT;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
|
|
|
#ifdef IN6_IFF_PRIVACY
|
|
|
|
if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
|
|
|
|
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
|
|
|
|
{
|
|
|
|
flags |= IFACE_PERMANENT;
|
|
|
|
valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
|
|
|
|
|
|
|
|
preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
|
|
|
|
|
|
|
|
if (netmask[i] != 0xff)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (i != IN6ADDRSZ && netmask[i])
|
|
|
|
|
|
|
|
for (j = 7; j > 0; j--, prefix++)
|
|
|
|
|
|
|
|
if ((netmask[i] & (1 << j)) == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* voodoo to clear interface field in address */
|
|
|
|
|
|
|
|
if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
addr->s6_addr[2] = 0;
|
|
|
|
|
|
|
|
addr->s6_addr[3] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!callback.af_inet6(addr, prefix, scope_id, iface_index, flags,
|
|
|
|
|
|
|
|
(unsigned int) preferred, (unsigned int)valid, parm))
|
|
|
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_DHCP6
|
|
|
|
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
|
|
|
else if (family == AF_LINK)
|
|
|
|
if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Assume ethernet again here */
|
|
|
|
valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
|
|
|
|
struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
|
|
|
|
preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
|
|
|
|
if (sdl->sdl_alen != 0 &&
|
|
|
|
|
|
|
|
!callback.af_local(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm))
|
|
|
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
|
|
|
|
|
|
|
|
if (netmask[i] != 0xff)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (i != IN6ADDRSZ && netmask[i])
|
|
|
|
|
|
|
|
for (j = 7; j > 0; j--, prefix++)
|
|
|
|
|
|
|
|
if ((netmask[i] & (1 << j)) == 0)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* voodoo to clear interface field in address */
|
|
|
|
|
|
|
|
if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
addr->s6_addr[2] = 0;
|
|
|
|
|
|
|
|
addr->s6_addr[3] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!callback.af_inet6(addr, prefix, scope_id, iface_index, flags,
|
|
|
|
|
|
|
|
(unsigned int) preferred, (unsigned int)valid, parm))
|
|
|
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_DHCP6
|
|
|
|
|
|
|
|
else if (family == AF_LINK)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Assume ethernet again here */
|
|
|
|
|
|
|
|
struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
|
|
|
|
|
|
|
|
if (sdl->sdl_alen != 0 &&
|
|
|
|
|
|
|
|
!callback.af_local(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm))
|
|
|
|
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
err:
|
|
|
|
errsave = errno;
|
|
|
|
errsave = errno;
|
|
|
|
freeifaddrs(head);
|
|
|
|
freeifaddrs(head);
|
|
|
|