1/* 2 * Copyright (c) 2000 - 2001 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 19 unchanged lines hidden (view full) --- 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifdef HAVE_CONFIG_H 35#include <config.h> |
36RCSID("$Id: getifaddrs.c,v 1.7 2001/11/30 03:27:30 assar Exp $"); |
37#endif 38#include "roken.h" 39 40#ifdef __osf__ 41/* hate */ 42struct rtentry; 43struct mbuf; 44#endif --- 16 unchanged lines hidden (view full) --- 61 int af, int siocgifconf, int siocgifflags, 62 size_t ifreq_sz) 63{ 64 int ret; 65 int fd; 66 size_t buf_size; 67 char *buf; 68 struct ifconf ifconf; |
69 char *p; 70 size_t sz; 71 struct sockaddr sa_zero; 72 struct ifreq *ifr; |
73 struct ifaddrs *start = NULL, **end = &start; |
74 |
75 buf = NULL; 76 77 memset (&sa_zero, 0, sizeof(sa_zero)); 78 fd = socket(af, SOCK_DGRAM, 0); 79 if (fd < 0) 80 return -1; 81 82 buf_size = 8192; --- 19 unchanged lines hidden (view full) --- 102 */ 103 104 if (ifconf.ifc_len < buf_size) 105 break; 106 free (buf); 107 buf_size *= 2; 108 } 109 |
110 for (p = ifconf.ifc_buf; 111 p < ifconf.ifc_buf + ifconf.ifc_len; 112 p += sz) { 113 struct ifreq ifreq; 114 struct sockaddr *sa; 115 size_t salen; 116 117 ifr = (struct ifreq *)p; --- 13 unchanged lines hidden (view full) --- 131 memcpy (ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name)); 132 133 if (ioctl(fd, siocgifflags, &ifreq) < 0) { 134 ret = errno; 135 goto error_out; 136 } 137 138 *end = malloc(sizeof(**end)); |
139 if (*end == NULL) { 140 ret = ENOMEM; 141 goto error_out; 142 } |
143 144 (*end)->ifa_next = NULL; 145 (*end)->ifa_name = strdup(ifr->ifr_name); 146 (*end)->ifa_flags = ifreq.ifr_flags; 147 (*end)->ifa_addr = malloc(salen); 148 memcpy((*end)->ifa_addr, sa, salen); 149 (*end)->ifa_netmask = NULL; 150 --- 18 unchanged lines hidden (view full) --- 169 end = &(*end)->ifa_next; 170 171 } 172 *ifap = start; 173 close(fd); 174 free(buf); 175 return 0; 176 error_out: |
177 freeifaddrs(start); |
178 close(fd); 179 free(buf); 180 errno = ret; 181 return -1; 182} 183 |
184#if defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS) 185static int 186getlifaddrs2(struct ifaddrs **ifap, 187 int af, int siocgifconf, int siocgifflags, 188 size_t ifreq_sz) 189{ 190 int ret; 191 int fd; 192 size_t buf_size; 193 char *buf; 194 struct lifconf ifconf; 195 char *p; 196 size_t sz; 197 struct sockaddr sa_zero; 198 struct lifreq *ifr; 199 struct ifaddrs *start = NULL, **end = &start; 200 201 buf = NULL; 202 203 memset (&sa_zero, 0, sizeof(sa_zero)); 204 fd = socket(af, SOCK_DGRAM, 0); 205 if (fd < 0) 206 return -1; 207 208 buf_size = 8192; 209 for (;;) { 210 buf = calloc(1, buf_size); 211 if (buf == NULL) { 212 ret = ENOMEM; 213 goto error_out; 214 } 215 ifconf.lifc_family = AF_UNSPEC; 216 ifconf.lifc_flags = 0; 217 ifconf.lifc_len = buf_size; 218 ifconf.lifc_buf = buf; 219 220 /* 221 * Solaris returns EINVAL when the buffer is too small. 222 */ 223 if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) { 224 ret = errno; 225 goto error_out; 226 } 227 /* 228 * Can the difference between a full and a overfull buf 229 * be determined? 230 */ 231 232 if (ifconf.lifc_len < buf_size) 233 break; 234 free (buf); 235 buf_size *= 2; 236 } 237 238 for (p = ifconf.lifc_buf; 239 p < ifconf.lifc_buf + ifconf.lifc_len; 240 p += sz) { 241 struct lifreq ifreq; 242 struct sockaddr_storage *sa; 243 size_t salen; 244 245 ifr = (struct lifreq *)p; 246 sa = &ifr->lifr_addr; 247 248 sz = ifreq_sz; 249 salen = sizeof(struct sockaddr_storage); 250#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN 251 salen = sa->sa_len; 252 sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len); 253#endif 254#ifdef SA_LEN 255 salen = SA_LEN(sa); 256 sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa)); 257#endif 258 memset (&ifreq, 0, sizeof(ifreq)); 259 memcpy (ifreq.lifr_name, ifr->lifr_name, sizeof(ifr->lifr_name)); 260 261 if (ioctl(fd, siocgifflags, &ifreq) < 0) { 262 ret = errno; 263 goto error_out; 264 } 265 266 *end = malloc(sizeof(**end)); 267 268 (*end)->ifa_next = NULL; 269 (*end)->ifa_name = strdup(ifr->lifr_name); 270 (*end)->ifa_flags = ifreq.lifr_flags; 271 (*end)->ifa_addr = malloc(salen); 272 memcpy((*end)->ifa_addr, sa, salen); 273 (*end)->ifa_netmask = NULL; 274 275#if 0 276 /* fix these when we actually need them */ 277 if(ifreq.ifr_flags & IFF_BROADCAST) { 278 (*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr)); 279 memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr, 280 sizeof(ifr->ifr_broadaddr)); 281 } else if(ifreq.ifr_flags & IFF_POINTOPOINT) { 282 (*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr)); 283 memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr, 284 sizeof(ifr->ifr_dstaddr)); 285 } else 286 (*end)->ifa_dstaddr = NULL; 287#else 288 (*end)->ifa_dstaddr = NULL; 289#endif 290 291 (*end)->ifa_data = NULL; 292 293 end = &(*end)->ifa_next; 294 295 } 296 *ifap = start; 297 close(fd); 298 free(buf); 299 return 0; 300 error_out: 301 freeifaddrs(start); 302 close(fd); 303 free(buf); 304 errno = ret; 305 return -1; 306} 307#endif /* defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS) */ 308 |
309int 310getifaddrs(struct ifaddrs **ifap) 311{ 312 int ret = -1; 313 errno = ENXIO; 314#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS) 315 if (ret) 316 ret = getifaddrs2 (ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS, 317 sizeof(struct in6_ifreq)); 318#endif |
319#if defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS) 320 if (ret) 321 ret = getlifaddrs2 (ifap, AF_INET6, SIOCGLIFCONF, SIOCGLIFFLAGS, 322 sizeof(struct lifreq)); 323#endif |
324#if defined(HAVE_IPV6) && defined(SIOCGIFCONF) 325 if (ret) 326 ret = getifaddrs2 (ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS, 327 sizeof(struct ifreq)); 328#endif 329#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS) 330 if (ret) 331 ret = getifaddrs2 (ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, --- 73 unchanged lines hidden --- |