windows: Provide a strndup(3) replacement
[strongswan.git] / src / libstrongswan / utils / windows.c
1 /*
2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "utils.h"
17
18 #include <errno.h>
19
20 /**
21 * See header
22 */
23 void windows_init()
24 {
25 WSADATA wsad;
26
27 /* initialize winsock2 */
28 WSAStartup(MAKEWORD(2, 2), &wsad);
29 }
30
31 /**
32 * See header
33 */
34 void windows_deinit()
35 {
36 WSACleanup();
37 }
38
39 /**
40 * See header
41 */
42 int usleep(useconds_t usec)
43 {
44 if (usec > 0 && usec < 1000)
45 { /* do not Sleep(0) for small values */
46 usec = 1000;
47 }
48 SleepEx(usec / 1000, TRUE);
49 return 0;
50 }
51
52 /**
53 * See header.
54 */
55 char* strndup(const char *s, size_t n)
56 {
57 char *dst;
58
59 n = min(strnlen(s, n), n);
60 dst = malloc(n + 1);
61 memcpy(dst, s, n);
62 dst[n] = '\0';
63
64 return dst;
65 }
66
67 /*
68 * See header.
69 */
70 void *dlopen(const char *filename, int flag)
71 {
72 return LoadLibrary(filename);
73 }
74
75 /**
76 * Load a symbol from known default libs (monolithic build)
77 */
78 static void* dlsym_default(const char *name)
79 {
80 const char *dlls[] = {
81 "libstrongswan-0.dll",
82 "libhydra-0.dll",
83 "libcharon-0.dll",
84 "libtnccs-0.dll",
85 NULL /* .exe */
86 };
87 HANDLE handle;
88 void *sym = NULL;
89 int i;
90
91 for (i = 0; i < countof(dlls); i++)
92 {
93 handle = GetModuleHandle(dlls[i]);
94 if (handle)
95 {
96 sym = GetProcAddress(handle, name);
97 if (sym)
98 {
99 break;
100 }
101 }
102 }
103 return sym;
104 }
105
106 /**
107 * Emulate RTLD_NEXT for some known symbols
108 */
109 static void* dlsym_next(const char *name)
110 {
111 struct {
112 const char *dll;
113 const char *syms[4];
114 } dlls[] = {
115 /* for leak detective */
116 { "msvcrt",
117 { "malloc", "calloc", "realloc", "free" }
118 },
119 };
120 HANDLE handle = NULL;
121 int i, j;
122
123 for (i = 0; i < countof(dlls); i++)
124 {
125 for (j = 0; j < countof(dlls[0].syms); j++)
126 {
127 if (dlls[i].syms[j] && streq(dlls[i].syms[j], name))
128 {
129 handle = GetModuleHandle(dlls[i].dll);
130 break;
131 }
132 }
133 }
134 if (handle)
135 {
136 return GetProcAddress(handle, name);
137 }
138 return handle;
139 }
140
141 /**
142 * See header.
143 */
144 void* dlsym(void *handle, const char *symbol)
145 {
146 if (handle == RTLD_DEFAULT)
147 {
148 return dlsym_default(symbol);
149 }
150 if (handle == RTLD_NEXT)
151 {
152 return dlsym_next(symbol);
153 }
154 return GetProcAddress((HMODULE)handle, symbol);
155 }
156
157 /**
158 * See header.
159 */
160 char* dlerror(void)
161 {
162 static char buf[128];
163 char *pos;
164 DWORD err;
165
166 err = GetLastError();
167 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
168 NULL, err, 0, buf, sizeof(buf), NULL) > 0)
169 {
170 pos = strchr(buf, '\n');
171 if (pos)
172 {
173 *pos = '\0';
174 }
175 }
176 else
177 {
178 snprintf(buf, sizeof(buf), "(%u)", err);
179 }
180 return buf;
181 }
182
183 /**
184 * See header.
185 */
186 int dlclose(void *handle)
187 {
188 return FreeLibrary((HMODULE)handle);
189 }
190
191 /**
192 * See header
193 */
194 int socketpair(int domain, int type, int protocol, int sv[2])
195 {
196 struct sockaddr_in addr = {
197 .sin_family = AF_INET,
198 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
199 };
200 socklen_t len = sizeof(addr);
201 int s, c, sc;
202 BOOL on;
203
204 /* We don't check domain for AF_INET, as we use it as replacement for
205 * AF_UNIX. */
206 if (type != SOCK_STREAM)
207 {
208 errno = EINVAL;
209 return -1;
210 }
211 if (protocol != 0 && protocol != IPPROTO_TCP)
212 {
213 errno = EINVAL;
214 return -1;
215 }
216 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
217 if (s == -1)
218 {
219 return -1;
220 }
221 c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
222 if (c == -1)
223 {
224 closesocket(c);
225 return -1;
226 }
227 if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == 0 &&
228 getsockname(s,(struct sockaddr*)&addr, &len) == 0 &&
229 listen(s, 0) == 0 &&
230 connect(c, (struct sockaddr*)&addr, sizeof(addr)) == 0)
231 {
232 sc = accept(s, NULL, NULL);
233 if (sc > 0)
234 {
235 closesocket(s);
236 s = sc;
237 if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
238 (void*)&on, sizeof(on)) == 0 &&
239 setsockopt(c, IPPROTO_TCP, TCP_NODELAY,
240 (void*)&on, sizeof(on)) == 0)
241 {
242 sv[0] = s;
243 sv[1] = c;
244 return 0;
245 }
246 }
247 }
248 closesocket(s);
249 closesocket(c);
250 return -1;
251 }
252
253 /**
254 * Set errno for a function setting WSA error on failure
255 */
256 static int wserr(int retval)
257 {
258 if (retval < 0)
259 {
260 switch (WSAGetLastError())
261 {
262 case WSANOTINITIALISED:
263 errno = EBADF;
264 break;
265 case WSAENETDOWN:
266 case WSAENETRESET:
267 case WSAESHUTDOWN:
268 errno = EPIPE;
269 break;
270 case WSAEACCES:
271 errno = EACCES;
272 break;
273 case WSAEINTR:
274 errno = EINTR;
275 break;
276 case WSAEINPROGRESS:
277 errno = EBUSY;
278 break;
279 case WSAEFAULT:
280 errno = EFAULT;
281 break;
282 case WSAENOBUFS:
283 errno = ENOMEM;
284 break;
285 case WSAENOTSOCK:
286 errno = EINVAL;
287 break;
288 case WSAEOPNOTSUPP:
289 errno = ENOSYS;
290 break;
291 case WSAEWOULDBLOCK:
292 errno = EWOULDBLOCK;
293 break;
294 case WSAEMSGSIZE:
295 errno = ENOSPC;
296 break;
297 case WSAEINVAL:
298 errno = EINVAL;
299 break;
300 case WSAENOTCONN:
301 case WSAEHOSTUNREACH:
302 case WSAECONNABORTED:
303 case WSAECONNRESET:
304 errno = EIO;
305 break;
306 case WSAETIMEDOUT:
307 errno = ESRCH;
308 break;
309 default:
310 errno = ENOENT;
311 break;
312 }
313 }
314 else
315 {
316 errno = 0;
317 }
318 return retval;
319 }
320
321 /**
322 * Check and clear the dontwait flag
323 */
324 static bool check_dontwait(int *flags)
325 {
326 if (*flags & MSG_DONTWAIT)
327 {
328 *flags &= ~MSG_DONTWAIT;
329 return TRUE;
330 }
331 return FALSE;
332 }
333
334 /**
335 * See header
336 */
337 #undef recv
338 ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags)
339 {
340 u_long on = 1, off = 0;
341 ssize_t outlen = -1;
342
343 if (!check_dontwait(&flags))
344 {
345 return wserr(recv(sockfd, buf, len, flags));
346 }
347 if (wserr(ioctlsocket(sockfd, FIONBIO, &on) == 0))
348 {
349 outlen = wserr(recv(sockfd, buf, len, flags));
350 ioctlsocket(sockfd, FIONBIO, &off);
351 }
352 return outlen;
353 }
354
355 /**
356 * See header
357 */
358 #undef recvfrom
359 ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
360 struct sockaddr *src_addr, socklen_t *addrlen)
361 {
362 u_long on = 1, off = 0;
363 ssize_t outlen = -1;
364
365 if (!check_dontwait(&flags))
366 {
367 return wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
368 }
369 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
370 {
371 outlen = wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
372 ioctlsocket(sockfd, FIONBIO, &off);
373 }
374 return outlen;
375 }
376
377 /**
378 * See header
379 */
380 #undef send
381 ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags)
382 {
383 u_long on = 1, off = 0;
384 ssize_t outlen = -1;
385
386 if (!check_dontwait(&flags))
387 {
388 return wserr(send(sockfd, buf, len, flags));
389 }
390 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
391 {
392 outlen = wserr(send(sockfd, buf, len, flags));
393 ioctlsocket(sockfd, FIONBIO, &off);
394 }
395 return outlen;
396 }
397
398 /**
399 * See header
400 */
401 #undef sendto
402 ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
403 const struct sockaddr *dest_addr, socklen_t addrlen)
404 {
405 u_long on = 1, off = 0;
406 ssize_t outlen = -1;
407
408 if (!check_dontwait(&flags))
409 {
410 return wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
411 }
412 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
413 {
414 outlen = wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
415 ioctlsocket(sockfd, FIONBIO, &off);
416 }
417 return outlen;
418 }