| /* |
| * "$Id: getifaddrs.c 6649 2007-07-11 21:46:42Z mike $" |
| * |
| * Network interface functions for the Common UNIX Printing System |
| * (CUPS) scheduler. |
| * |
| * Copyright 2007 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/". |
| * |
| * Contents: |
| * |
| * _cups_getifaddrs() - Get a list of network interfaces on the system. |
| * _cups_freeifaddrs() - Free an interface list... |
| */ |
| |
| /* |
| * 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 */ |
| |
| |
| /* |
| * End of "$Id: getifaddrs.c 6649 2007-07-11 21:46:42Z mike $". |
| */ |