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