#include "http-private.h"
#ifndef HAVE_GETIFADDRS
int
_cups_getifaddrs(struct ifaddrs **addrs)
{
int sock;
char buffer[65536],
*bufptr,
*bufend;
struct ifconf conf;
struct sockaddr addr;
struct ifreq *ifp;
int ifpsize;
struct ifaddrs *temp;
struct ifreq request;
if (addrs == NULL)
return (-1);
*addrs = NULL;
memset (&addr, 0, sizeof(addr));
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return (-1);
conf.ifc_len = sizeof(buffer);
conf.ifc_buf = buffer;
if (ioctl(sock, SIOCGIFCONF, &conf) < 0)
{
close(sock);
return (-1);
}
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
# define sockaddr_len(a) ((a)->sa_len)
# else
# define sockaddr_len(a) (sizeof(struct sockaddr))
# endif
for (bufptr = buffer, bufend = buffer + conf.ifc_len;
bufptr < bufend;
bufptr += ifpsize)
{
ifp = (struct ifreq *)bufptr;
ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr));
if (ifpsize < sizeof(struct ifreq))
ifpsize = sizeof(struct ifreq);
memset(&request, 0, sizeof(request));
memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name));
if (ioctl(sock, SIOCGIFFLAGS, &request) < 0)
continue;
if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL)
{
close(sock);
return (-1);
}
temp->ifa_next = *addrs;
*addrs = temp;
temp->ifa_name = strdup(ifp->ifr_name);
temp->ifa_flags = request.ifr_flags;
if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL)
memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr)));
if (!ioctl(sock, SIOCGIFNETMASK, &request))
{
if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL)
memcpy(temp->ifa_netmask, &(request.ifr_netmask),
sizeof(request.ifr_netmask));
}
if (temp->ifa_flags & IFF_BROADCAST)
{
if (!ioctl(sock, SIOCGIFBRDADDR, &request))
{
if ((temp->ifa_broadaddr =
calloc(1, sizeof(request.ifr_broadaddr))) != NULL)
memcpy(temp->ifa_broadaddr, &(request.ifr_broadaddr),
sizeof(request.ifr_broadaddr));
}
}
else if (temp->ifa_flags & IFF_POINTOPOINT)
{
if (!ioctl(sock, SIOCGIFDSTADDR, &request))
{
temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr));
memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr),
sizeof(request.ifr_dstaddr));
}
}
}
close(sock);
return (0);
}
void
_cups_freeifaddrs(struct ifaddrs *addrs)
{
struct ifaddrs *next;
while (addrs != NULL)
{
next = addrs->ifa_next;
if (addrs->ifa_name)
{
free(addrs->ifa_name);
addrs->ifa_name = NULL;
}
if (addrs->ifa_addr)
{
free(addrs->ifa_addr);
addrs->ifa_addr = NULL;
}
if (addrs->ifa_netmask)
{
free(addrs->ifa_netmask);
addrs->ifa_netmask = NULL;
}
if (addrs->ifa_dstaddr)
{
free(addrs->ifa_dstaddr);
addrs->ifa_dstaddr = NULL;
}
free(addrs);
addrs = next;
}
}
#endif