You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
5.2 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* Network interface functions for CUPS.
*
* Copyright © 2007-2018 by Apple Inc.
* Copyright © 1997-2006 by Easy Software Products, all rights reserved.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
* information.
*/
/*
* Include necessary headers.
*/
#include "getifaddrs-internal.h"
#ifndef HAVE_GETIFADDRS
/*
* '_cups_getifaddrs()' - Get a list of network interfaces on the system.
*/
int /* O - 0 on success, -1 on error */
_cups_getifaddrs(struct ifaddrs **addrs)/* O - List of interfaces */
{
int sock; /* Socket */
char buffer[65536], /* Buffer for address info */
*bufptr, /* Pointer into buffer */
*bufend; /* End of buffer */
struct ifconf conf; /* Interface configurations */
struct sockaddr addr; /* Address data */
struct ifreq *ifp; /* Interface data */
int ifpsize; /* Size of interface data */
struct ifaddrs *temp; /* Pointer to current interface */
struct ifreq request; /* Interface request */
/*
* Start with an empty list...
*/
if (addrs == NULL)
return (-1);
*addrs = NULL;
/*
* Create a UDP socket to get the interface data...
*/
memset (&addr, 0, sizeof(addr));
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return (-1);
/*
* Try to get the list of interfaces...
*/
conf.ifc_len = sizeof(buffer);
conf.ifc_buf = buffer;
if (ioctl(sock, SIOCGIFCONF, &conf) < 0)
{
/*
* Couldn't get the list of interfaces...
*/
close(sock);
return (-1);
}
/*
* OK, got the list of interfaces, now lets step through the
* buffer to pull them out...
*/
# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
# define sockaddr_len(a) ((a)->sa_len)
# else
# define sockaddr_len(a) (sizeof(struct sockaddr))
# endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
for (bufptr = buffer, bufend = buffer + conf.ifc_len;
bufptr < bufend;
bufptr += ifpsize)
{
/*
* Get the current interface information...
*/
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));
/*
* Check the status of the interface...
*/
if (ioctl(sock, SIOCGIFFLAGS, &request) < 0)
continue;
/*
* Allocate memory for a single interface record...
*/
if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL)
{
/*
* Unable to allocate memory...
*/
close(sock);
return (-1);
}
/*
* Add this record to the front of the list and copy the name, flags,
* and network address...
*/
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)));
/*
* Try to get the netmask for the interface...
*/
if (!ioctl(sock, SIOCGIFNETMASK, &request))
{
/*
* Got it, make a copy...
*/
if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL)
memcpy(temp->ifa_netmask, &(request.ifr_netmask),
sizeof(request.ifr_netmask));
}
/*
* Then get the broadcast or point-to-point (destination) address,
* if applicable...
*/
if (temp->ifa_flags & IFF_BROADCAST)
{
/*
* Have a broadcast address, so get it!
*/
if (!ioctl(sock, SIOCGIFBRDADDR, &request))
{
/*
* Got it, make a copy...
*/
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)
{
/*
* Point-to-point interface; grab the remote address...
*/
if (!ioctl(sock, SIOCGIFDSTADDR, &request))
{
temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr));
memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr),
sizeof(request.ifr_dstaddr));
}
}
}
/*
* OK, we're done with the socket, close it and return 0...
*/
close(sock);
return (0);
}
/*
* '_cups_freeifaddrs()' - Free an interface list...
*/
void
_cups_freeifaddrs(struct ifaddrs *addrs)/* I - Interface list to free */
{
struct ifaddrs *next; /* Next interface in list */
while (addrs != NULL)
{
/*
* Make a copy of the next interface pointer...
*/
next = addrs->ifa_next;
/*
* Free data values as needed...
*/
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 this node and continue to the next...
*/
free(addrs);
addrs = next;
}
}
#endif /* !HAVE_GETIFADDRS */