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