1/*********************************************************************** 2 * Copyright (c) 2009, Secure Endpoints Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 **********************************************************************/ 31 32#include<config.h> 33 34#include <roken.h> 35 36#include <ifaddrs.h> 37 38#ifndef _WIN32 39#error This is a Windows specific implementation. 40#endif 41 42static struct sockaddr * 43dupaddr(const sockaddr_gen * src) 44{ 45 sockaddr_gen * d = malloc(sizeof(*d)); 46 47 if (d) { 48 memcpy(d, src, sizeof(*d)); 49 } 50 51 return (struct sockaddr *) d; 52} 53 54int ROKEN_LIB_FUNCTION 55rk_getifaddrs(struct ifaddrs **ifpp) 56{ 57 SOCKET s = INVALID_SOCKET; 58 size_t il_len = 8192; 59 int ret = -1; 60 INTERFACE_INFO *il = NULL; 61 62 *ifpp = NULL; 63 64 s = socket(AF_INET, SOCK_DGRAM, 0); 65 if (s == INVALID_SOCKET) 66 return -1; 67 68 for (;;) { 69 DWORD cbret = 0; 70 71 il = malloc(il_len); 72 if (!il) 73 break; 74 75 ZeroMemory(il, il_len); 76 77 if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, 78 (LPVOID) il, (DWORD) il_len, &cbret, 79 NULL, NULL) == 0) { 80 il_len = cbret; 81 break; 82 } 83 84 free (il); 85 il = NULL; 86 87 if (WSAGetLastError() == WSAEFAULT && cbret > il_len) { 88 il_len = cbret; 89 } else { 90 break; 91 } 92 } 93 94 if (!il) 95 goto _exit; 96 97 /* il is an array of INTERFACE_INFO structures. il_len has the 98 actual size of the buffer. The number of elements is 99 il_len/sizeof(INTERFACE_INFO) */ 100 101 { 102 size_t n = il_len / sizeof(INTERFACE_INFO); 103 size_t i; 104 105 for (i = 0; i < n; i++ ) { 106 struct ifaddrs *ifp; 107 108 ifp = malloc(sizeof(*ifp)); 109 if (ifp == NULL) 110 break; 111 112 ZeroMemory(ifp, sizeof(*ifp)); 113 114 ifp->ifa_next = NULL; 115 ifp->ifa_name = NULL; 116 ifp->ifa_flags = il[i].iiFlags; 117 ifp->ifa_addr = dupaddr(&il[i].iiAddress); 118 ifp->ifa_netmask = dupaddr(&il[i].iiNetmask); 119 ifp->ifa_broadaddr = dupaddr(&il[i].iiBroadcastAddress); 120 ifp->ifa_data = NULL; 121 122 *ifpp = ifp; 123 ifpp = &ifp->ifa_next; 124 } 125 126 if (i == n) 127 ret = 0; 128 } 129 130 _exit: 131 132 if (s != INVALID_SOCKET) 133 closesocket(s); 134 135 if (il) 136 free (il); 137 138 return ret; 139} 140 141void ROKEN_LIB_FUNCTION 142rk_freeifaddrs(struct ifaddrs *ifp) 143{ 144 struct ifaddrs *p, *q; 145 146 for(p = ifp; p; ) { 147 if (p->ifa_name) 148 free(p->ifa_name); 149 if(p->ifa_addr) 150 free(p->ifa_addr); 151 if(p->ifa_dstaddr) 152 free(p->ifa_dstaddr); 153 if(p->ifa_netmask) 154 free(p->ifa_netmask); 155 if(p->ifa_data) 156 free(p->ifa_data); 157 q = p; 158 p = p->ifa_next; 159 free(q); 160 } 161} 162