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.
254 lines
5.4 KiB
254 lines
5.4 KiB
/* |
|
* Network interface functions for CUPS. |
|
* |
|
* Copyright 2007-2010 by Apple Inc. |
|
* Copyright 1997-2006 by Easy Software Products, all rights reserved. |
|
* |
|
* These coded instructions, statements, and computer programs are the |
|
* property of Apple Inc. and are protected by Federal copyright |
|
* law. Distribution and use rights are outlined in the file "LICENSE.txt" |
|
* "LICENSE" which should have been included with this file. If this |
|
* file is missing or damaged, see the license at "http://www.cups.org/". |
|
*/ |
|
|
|
/* |
|
* Include necessary headers. |
|
*/ |
|
|
|
#include "http-private.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 */
|
|
|