1/* 2 * "$Id: getifaddrs.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * Network interface functions for CUPS. 5 * 6 * Copyright 2007-2010 by Apple Inc. 7 * Copyright 1997-2006 by Easy Software Products, all rights reserved. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * "LICENSE" which should have been included with this file. If this 13 * file is missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * Contents: 16 * 17 * _cups_getifaddrs() - Get a list of network interfaces on the system. 18 * _cups_freeifaddrs() - Free an interface list... 19 */ 20 21/* 22 * Include necessary headers. 23 */ 24 25#include "http-private.h" 26 27 28#ifndef HAVE_GETIFADDRS 29/* 30 * '_cups_getifaddrs()' - Get a list of network interfaces on the system. 31 */ 32 33int /* O - 0 on success, -1 on error */ 34_cups_getifaddrs(struct ifaddrs **addrs)/* O - List of interfaces */ 35{ 36 int sock; /* Socket */ 37 char buffer[65536], /* Buffer for address info */ 38 *bufptr, /* Pointer into buffer */ 39 *bufend; /* End of buffer */ 40 struct ifconf conf; /* Interface configurations */ 41 struct sockaddr addr; /* Address data */ 42 struct ifreq *ifp; /* Interface data */ 43 int ifpsize; /* Size of interface data */ 44 struct ifaddrs *temp; /* Pointer to current interface */ 45 struct ifreq request; /* Interface request */ 46 47 48 /* 49 * Start with an empty list... 50 */ 51 52 if (addrs == NULL) 53 return (-1); 54 55 *addrs = NULL; 56 57 /* 58 * Create a UDP socket to get the interface data... 59 */ 60 61 memset (&addr, 0, sizeof(addr)); 62 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 63 return (-1); 64 65 /* 66 * Try to get the list of interfaces... 67 */ 68 69 conf.ifc_len = sizeof(buffer); 70 conf.ifc_buf = buffer; 71 72 if (ioctl(sock, SIOCGIFCONF, &conf) < 0) 73 { 74 /* 75 * Couldn't get the list of interfaces... 76 */ 77 78 close(sock); 79 return (-1); 80 } 81 82 /* 83 * OK, got the list of interfaces, now lets step through the 84 * buffer to pull them out... 85 */ 86 87# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 88# define sockaddr_len(a) ((a)->sa_len) 89# else 90# define sockaddr_len(a) (sizeof(struct sockaddr)) 91# endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ 92 93 for (bufptr = buffer, bufend = buffer + conf.ifc_len; 94 bufptr < bufend; 95 bufptr += ifpsize) 96 { 97 /* 98 * Get the current interface information... 99 */ 100 101 ifp = (struct ifreq *)bufptr; 102 ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr)); 103 104 if (ifpsize < sizeof(struct ifreq)) 105 ifpsize = sizeof(struct ifreq); 106 107 memset(&request, 0, sizeof(request)); 108 memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name)); 109 110 /* 111 * Check the status of the interface... 112 */ 113 114 if (ioctl(sock, SIOCGIFFLAGS, &request) < 0) 115 continue; 116 117 /* 118 * Allocate memory for a single interface record... 119 */ 120 121 if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL) 122 { 123 /* 124 * Unable to allocate memory... 125 */ 126 127 close(sock); 128 return (-1); 129 } 130 131 /* 132 * Add this record to the front of the list and copy the name, flags, 133 * and network address... 134 */ 135 136 temp->ifa_next = *addrs; 137 *addrs = temp; 138 temp->ifa_name = strdup(ifp->ifr_name); 139 temp->ifa_flags = request.ifr_flags; 140 if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL) 141 memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr))); 142 143 /* 144 * Try to get the netmask for the interface... 145 */ 146 147 if (!ioctl(sock, SIOCGIFNETMASK, &request)) 148 { 149 /* 150 * Got it, make a copy... 151 */ 152 153 if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL) 154 memcpy(temp->ifa_netmask, &(request.ifr_netmask), 155 sizeof(request.ifr_netmask)); 156 } 157 158 /* 159 * Then get the broadcast or point-to-point (destination) address, 160 * if applicable... 161 */ 162 163 if (temp->ifa_flags & IFF_BROADCAST) 164 { 165 /* 166 * Have a broadcast address, so get it! 167 */ 168 169 if (!ioctl(sock, SIOCGIFBRDADDR, &request)) 170 { 171 /* 172 * Got it, make a copy... 173 */ 174 175 if ((temp->ifa_broadaddr = 176 calloc(1, sizeof(request.ifr_broadaddr))) != NULL) 177 memcpy(temp->ifa_broadaddr, &(request.ifr_broadaddr), 178 sizeof(request.ifr_broadaddr)); 179 } 180 } 181 else if (temp->ifa_flags & IFF_POINTOPOINT) 182 { 183 /* 184 * Point-to-point interface; grab the remote address... 185 */ 186 187 if (!ioctl(sock, SIOCGIFDSTADDR, &request)) 188 { 189 temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr)); 190 memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr), 191 sizeof(request.ifr_dstaddr)); 192 } 193 } 194 } 195 196 /* 197 * OK, we're done with the socket, close it and return 0... 198 */ 199 200 close(sock); 201 202 return (0); 203} 204 205 206/* 207 * '_cups_freeifaddrs()' - Free an interface list... 208 */ 209 210void 211_cups_freeifaddrs(struct ifaddrs *addrs)/* I - Interface list to free */ 212{ 213 struct ifaddrs *next; /* Next interface in list */ 214 215 216 while (addrs != NULL) 217 { 218 /* 219 * Make a copy of the next interface pointer... 220 */ 221 222 next = addrs->ifa_next; 223 224 /* 225 * Free data values as needed... 226 */ 227 228 if (addrs->ifa_name) 229 { 230 free(addrs->ifa_name); 231 addrs->ifa_name = NULL; 232 } 233 234 if (addrs->ifa_addr) 235 { 236 free(addrs->ifa_addr); 237 addrs->ifa_addr = NULL; 238 } 239 240 if (addrs->ifa_netmask) 241 { 242 free(addrs->ifa_netmask); 243 addrs->ifa_netmask = NULL; 244 } 245 246 if (addrs->ifa_dstaddr) 247 { 248 free(addrs->ifa_dstaddr); 249 addrs->ifa_dstaddr = NULL; 250 } 251 252 /* 253 * Free this node and continue to the next... 254 */ 255 256 free(addrs); 257 258 addrs = next; 259 } 260} 261#endif /* !HAVE_GETIFADDRS */ 262 263 264/* 265 * End of "$Id: getifaddrs.c 11093 2013-07-03 20:48:42Z msweet $". 266 */ 267