1f22ffa028a9cd6eb248b75e5f9483c8af61de76
[strongswan.git] / src / libstrongswan / utils / compat / 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 /* WSAPoll() */
17 #define _WIN32_WINNT 0x0600
18
19 #include <utils/utils.h>
20
21 #include <errno.h>
22
23 /**
24 * See header
25 */
26 void windows_init()
27 {
28 WSADATA wsad;
29
30 /* initialize winsock2 */
31 WSAStartup(MAKEWORD(2, 2), &wsad);
32 }
33
34 /**
35 * See header
36 */
37 void windows_deinit()
38 {
39 WSACleanup();
40 }
41
42 /**
43 * See header
44 */
45 int usleep(useconds_t usec)
46 {
47 if (usec > 0 && usec < 1000)
48 { /* do not Sleep(0) for small values */
49 usec = 1000;
50 }
51 SleepEx(usec / 1000, TRUE);
52 return 0;
53 }
54
55 /**
56 * See header.
57 */
58 char* strndup(const char *s, size_t n)
59 {
60 char *dst;
61
62 n = min(strnlen(s, n), n);
63 dst = malloc(n + 1);
64 memcpy(dst, s, n);
65 dst[n] = '\0';
66
67 return dst;
68 }
69
70 /*
71 * See header.
72 */
73 void *dlopen(const char *filename, int flag)
74 {
75 return LoadLibrary(filename);
76 }
77
78 /**
79 * Load a symbol from known default libs (monolithic build)
80 */
81 static void* dlsym_default(const char *name)
82 {
83 const char *dlls[] = {
84 "libstrongswan-0.dll",
85 "libhydra-0.dll",
86 "libcharon-0.dll",
87 "libtnccs-0.dll",
88 NULL /* .exe */
89 };
90 HANDLE handle;
91 void *sym = NULL;
92 int i;
93
94 for (i = 0; i < countof(dlls); i++)
95 {
96 handle = GetModuleHandle(dlls[i]);
97 if (handle)
98 {
99 sym = GetProcAddress(handle, name);
100 if (sym)
101 {
102 break;
103 }
104 }
105 }
106 return sym;
107 }
108
109 /**
110 * Emulate RTLD_NEXT for some known symbols
111 */
112 static void* dlsym_next(const char *name)
113 {
114 struct {
115 const char *dll;
116 const char *syms[4];
117 } dlls[] = {
118 /* for leak detective */
119 { "msvcrt",
120 { "malloc", "calloc", "realloc", "free" }
121 },
122 };
123 HANDLE handle = NULL;
124 int i, j;
125
126 for (i = 0; i < countof(dlls); i++)
127 {
128 for (j = 0; j < countof(dlls[0].syms); j++)
129 {
130 if (dlls[i].syms[j] && streq(dlls[i].syms[j], name))
131 {
132 handle = GetModuleHandle(dlls[i].dll);
133 break;
134 }
135 }
136 }
137 if (handle)
138 {
139 return GetProcAddress(handle, name);
140 }
141 return handle;
142 }
143
144 /**
145 * See header.
146 */
147 void* dlsym(void *handle, const char *symbol)
148 {
149 if (handle == RTLD_DEFAULT)
150 {
151 return dlsym_default(symbol);
152 }
153 if (handle == RTLD_NEXT)
154 {
155 return dlsym_next(symbol);
156 }
157 return GetProcAddress((HMODULE)handle, symbol);
158 }
159
160 /**
161 * See header.
162 */
163 char* dlerror(void)
164 {
165 static char buf[128];
166 char *pos;
167 DWORD err;
168
169 err = GetLastError();
170 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
171 NULL, err, 0, buf, sizeof(buf), NULL) > 0)
172 {
173 pos = strchr(buf, '\n');
174 if (pos)
175 {
176 *pos = '\0';
177 }
178 }
179 else
180 {
181 snprintf(buf, sizeof(buf), "(%u)", err);
182 }
183 return buf;
184 }
185
186 /**
187 * See header.
188 */
189 int dlclose(void *handle)
190 {
191 return FreeLibrary((HMODULE)handle);
192 }
193
194 /**
195 * See header
196 */
197 int socketpair(int domain, int type, int protocol, int sv[2])
198 {
199 struct sockaddr_in addr = {
200 .sin_family = AF_INET,
201 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
202 };
203 socklen_t len = sizeof(addr);
204 int s, c, sc;
205 BOOL on;
206
207 /* We don't check domain for AF_INET, as we use it as replacement for
208 * AF_UNIX. */
209 if (type != SOCK_STREAM)
210 {
211 errno = EINVAL;
212 return -1;
213 }
214 if (protocol != 0 && protocol != IPPROTO_TCP)
215 {
216 errno = EINVAL;
217 return -1;
218 }
219 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
220 if (s == -1)
221 {
222 return -1;
223 }
224 c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
225 if (c == -1)
226 {
227 closesocket(s);
228 return -1;
229 }
230 if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == 0 &&
231 getsockname(s,(struct sockaddr*)&addr, &len) == 0 &&
232 listen(s, 0) == 0 &&
233 connect(c, (struct sockaddr*)&addr, sizeof(addr)) == 0)
234 {
235 sc = accept(s, NULL, NULL);
236 if (sc >= 0)
237 {
238 closesocket(s);
239 s = sc;
240 if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
241 (void*)&on, sizeof(on)) == 0 &&
242 setsockopt(c, IPPROTO_TCP, TCP_NODELAY,
243 (void*)&on, sizeof(on)) == 0)
244 {
245 sv[0] = s;
246 sv[1] = c;
247 return 0;
248 }
249 }
250 }
251 closesocket(s);
252 closesocket(c);
253 return -1;
254 }
255
256 /**
257 * See header
258 */
259 char* getpass(const char *prompt)
260 {
261 static char buf[64] = "";
262 char *pos;
263 HANDLE in, out;
264 DWORD mode, written = 0, total, done;
265
266 out = GetStdHandle(STD_OUTPUT_HANDLE);
267 in = GetStdHandle(STD_INPUT_HANDLE);
268
269 if (out == INVALID_HANDLE_VALUE || in == INVALID_HANDLE_VALUE ||
270 !GetConsoleMode(out, &mode) || !GetConsoleMode(in, &mode))
271 {
272 return NULL;
273 }
274
275 total = strlen(prompt);
276 while (written < total)
277 {
278 if (!WriteConsole(out, prompt + written, total - written, &done, NULL))
279 {
280 return NULL;
281 }
282 written += done;
283 }
284
285 if (!SetConsoleMode(in, mode & ~ENABLE_ECHO_INPUT))
286 {
287 return NULL;
288 }
289
290 while (TRUE)
291 {
292 if (!ReadConsole(in, buf, sizeof(buf), &done, NULL))
293 {
294 SetConsoleMode(in, mode);
295 return NULL;
296 }
297 buf[sizeof(buf)-1] = '\0';
298
299 if (done)
300 {
301 pos = strchr(buf, '\r');
302 if (pos)
303 {
304 *pos = '\0';
305 }
306 break;
307 }
308 }
309 SetConsoleMode(in, mode);
310
311 /* append a newline, as we have no echo during input */
312 WriteConsole(out, "\r\n", 2, &done, NULL);
313
314 return buf;
315 }
316
317 /**
318 * See header.
319 */
320 #undef strerror_s
321 int strerror_s_extended(char *buf, size_t buflen, int errnum)
322 {
323 const char *errstr [] = {
324 /* EADDRINUSE */ "Address in use",
325 /* EADDRNOTAVAIL */ "Address not available",
326 /* EAFNOSUPPORT */ "Address family not supported",
327 /* EALREADY */ "Connection already in progress",
328 /* EBADMSG */ "Bad message",
329 /* ECANCELED */ "Operation canceled",
330 /* ECONNABORTED */ "Connection aborted",
331 /* ECONNREFUSED */ "Connection refused",
332 /* ECONNRESET */ "Connection reset",
333 /* EDESTADDRREQ */ "Destination address required",
334 /* EHOSTUNREACH */ "Host is unreachable",
335 /* EIDRM */ "Identifier removed",
336 /* EINPROGRESS */ "Operation in progress",
337 /* EISCONN */ "Socket is connected",
338 /* ELOOP */ "Too many levels of symbolic links",
339 /* EMSGSIZE */ "Message too large",
340 /* ENETDOWN */ "Network is down",
341 /* ENETRESET */ "Connection aborted by network",
342 /* ENETUNREACH */ "Network unreachable",
343 /* ENOBUFS */ "No buffer space available",
344 /* ENODATA */ "No message is available",
345 /* ENOLINK */ "No link",
346 /* ENOMSG */ "No message of the desired type",
347 /* ENOPROTOOPT */ "Protocol not available",
348 /* ENOSR */ "No stream resources",
349 /* ENOSTR */ "Not a stream",
350 /* ENOTCONN */ "The socket is not connected",
351 /* ENOTRECOVERABLE */ "State not recoverable",
352 /* ENOTSOCK */ "Not a socket",
353 /* ENOTSUP */ "Not supported",
354 /* EOPNOTSUPP */ "Operation not supported on socket",
355 /* EOTHER */ "Other error",
356 /* EOVERFLOW */ "Value too large to be stored in data type",
357 /* EOWNERDEAD */ "Previous owner died",
358 /* EPROTO */ "Protocol error",
359 /* EPROTONOSUPPORT */ "Protocol not supported",
360 /* EPROTOTYPE */ "Protocol wrong type for socket",
361 /* ETIME */ "Timeout",
362 /* ETIMEDOUT */ "Connection timed out",
363 /* ETXTBSY */ "Text file busy",
364 /* EWOULDBLOCK */ "Operation would block",
365 };
366 int offset = EADDRINUSE;
367
368 if (errnum < offset || errnum >= offset + countof(errstr))
369 {
370 return strerror_s(buf, buflen, errnum);
371 }
372 strncpy(buf, errstr[errnum - offset], buflen);
373 buf[buflen - 1] = '\0';
374 return 0;
375 }
376
377 /**
378 * Set errno for a function setting WSA error on failure
379 */
380 static int wserr(int retval)
381 {
382 if (retval < 0)
383 {
384 static const struct {
385 DWORD wsa;
386 int err;
387 } map[] = {
388 { WSANOTINITIALISED, EBADF },
389 { WSAENETDOWN, ENETDOWN },
390 { WSAENETRESET, ENETRESET },
391 { WSAECONNABORTED, ECONNABORTED },
392 { WSAESHUTDOWN, ECONNABORTED },
393 { WSAEACCES, EACCES },
394 { WSAEINTR, EINTR },
395 { WSAEINPROGRESS, EINPROGRESS },
396 { WSAEFAULT, EFAULT },
397 { WSAENOBUFS, ENOBUFS },
398 { WSAENOTSOCK, ENOTSOCK },
399 { WSAEOPNOTSUPP, EOPNOTSUPP },
400 { WSAEWOULDBLOCK, EWOULDBLOCK },
401 { WSAEMSGSIZE, EMSGSIZE },
402 { WSAEINVAL, EINVAL },
403 { WSAENOTCONN, ENOTCONN },
404 { WSAEHOSTUNREACH, EHOSTUNREACH },
405 { WSAENETUNREACH, ENETUNREACH },
406 { WSAECONNABORTED, ECONNABORTED },
407 { WSAECONNRESET, ECONNRESET },
408 { WSAETIMEDOUT, ETIMEDOUT },
409 { WSAEMFILE, EMFILE },
410 { WSAEALREADY, EALREADY },
411 { WSAEDESTADDRREQ, EDESTADDRREQ },
412 { WSAEISCONN, EISCONN },
413 { WSAEOPNOTSUPP, EOPNOTSUPP },
414 { WSAEPROTOTYPE, EPROTOTYPE },
415 { WSAENOPROTOOPT, ENOPROTOOPT },
416 { WSAEPROTONOSUPPORT, EPROTONOSUPPORT },
417 { WSAEPFNOSUPPORT, EPROTONOSUPPORT },
418 { WSAEAFNOSUPPORT, EAFNOSUPPORT },
419 { WSAEADDRNOTAVAIL, EADDRNOTAVAIL },
420 { WSAEADDRINUSE, EADDRINUSE },
421 { WSAETIMEDOUT, ETIMEDOUT },
422 { WSAECONNREFUSED, ECONNREFUSED },
423 { WSAELOOP, ELOOP },
424 { WSAENAMETOOLONG, ENAMETOOLONG },
425 { WSAENOTEMPTY, ENOTEMPTY },
426 { WSAEPROTOTYPE, EPROTOTYPE },
427 { WSAVERNOTSUPPORTED, ENOTSUP },
428 };
429 DWORD wsa, i;
430
431 wsa = WSAGetLastError();
432 for (i = 0; i < countof(map); i++)
433 {
434 if (map[i].wsa == wsa)
435 {
436 errno = map[i].err;
437 return retval;
438 }
439 }
440 errno = ENOENT;
441 return retval;
442 }
443 errno = 0;
444 return retval;
445 }
446
447 /**
448 * Check and clear the dontwait flag
449 */
450 static bool check_dontwait(int *flags)
451 {
452 if (*flags & MSG_DONTWAIT)
453 {
454 *flags &= ~MSG_DONTWAIT;
455 return TRUE;
456 }
457 return FALSE;
458 }
459
460 /**
461 * See header
462 */
463 #undef shutdown
464 int windows_shutdown(int sockfd, int how)
465 {
466 return wserr(shutdown(sockfd, how));
467 }
468
469 /**
470 * See header
471 */
472 #undef accept
473 int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
474 {
475 return wserr(accept(sockfd, addr, addrlen));
476 }
477
478 /**
479 * See header
480 */
481 #undef bind
482 int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
483 {
484 return wserr(bind(sockfd, addr, addrlen));
485 }
486
487 /**
488 * See header
489 */
490 #undef connect
491 int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
492 {
493 return wserr(connect(sockfd, addr, addrlen));
494 }
495
496 /**
497 * See header
498 */
499 #undef getsockname
500 int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
501 {
502 return wserr(getsockname(sockfd, addr, addrlen));
503 }
504
505 /**
506 * See header
507 */
508 #undef getsockopt
509 int windows_getsockopt(int sockfd, int level, int optname,
510 void *optval, socklen_t *optlen)
511 {
512 return wserr(getsockopt(sockfd, level, optname, optval, optlen));
513 }
514
515 /**
516 * See header
517 */
518 #undef setsockopt
519 int windows_setsockopt(int sockfd, int level, int optname,
520 const void *optval, socklen_t optlen)
521 {
522 return wserr(setsockopt(sockfd, level, optname, optval, optlen));
523 }
524
525 /**
526 * See header
527 */
528 #undef socket
529 int windows_socket(int domain, int type, int protocol)
530 {
531 return wserr(socket(domain, type, protocol));
532 }
533
534 /**
535 * See header
536 */
537 #undef select
538 int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
539 fd_set *exceptfds, struct timeval *timeout)
540 {
541 return wserr(select(nfds, readfds, writefds, exceptfds, timeout));
542 }
543
544 /**
545 * See header
546 */
547 #undef close
548 int windows_close(int fd)
549 {
550 int ret;
551
552 ret = close(fd);
553 if (ret == -1 && errno == EBADF)
554 { /* Winsock socket? */
555 ret = wserr(closesocket(fd));
556 }
557 return ret;
558 }
559
560 /**
561 * See header
562 */
563 #undef recv
564 ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags)
565 {
566 u_long on = 1, off = 0;
567 ssize_t outlen = -1;
568
569 if (!check_dontwait(&flags))
570 {
571 return wserr(recv(sockfd, buf, len, flags));
572 }
573 if (wserr(ioctlsocket(sockfd, FIONBIO, &on) == 0))
574 {
575 outlen = wserr(recv(sockfd, buf, len, flags));
576 ioctlsocket(sockfd, FIONBIO, &off);
577 }
578 return outlen;
579 }
580
581 /**
582 * See header
583 */
584 #undef recvfrom
585 ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
586 struct sockaddr *src_addr, socklen_t *addrlen)
587 {
588 u_long on = 1, off = 0;
589 ssize_t outlen = -1;
590
591 if (!check_dontwait(&flags))
592 {
593 return wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
594 }
595 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
596 {
597 outlen = wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
598 ioctlsocket(sockfd, FIONBIO, &off);
599 }
600 return outlen;
601 }
602
603 /**
604 * See header
605 */
606 #undef send
607 ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags)
608 {
609 u_long on = 1, off = 0;
610 ssize_t outlen = -1;
611
612 if (!check_dontwait(&flags))
613 {
614 return wserr(send(sockfd, buf, len, flags));
615 }
616 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
617 {
618 outlen = wserr(send(sockfd, buf, len, flags));
619 ioctlsocket(sockfd, FIONBIO, &off);
620 }
621 return outlen;
622 }
623
624 /**
625 * See header
626 */
627 #undef sendto
628 ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
629 const struct sockaddr *dest_addr, socklen_t addrlen)
630 {
631 u_long on = 1, off = 0;
632 ssize_t outlen = -1;
633
634 if (!check_dontwait(&flags))
635 {
636 return wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
637 }
638 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
639 {
640 outlen = wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
641 ioctlsocket(sockfd, FIONBIO, &off);
642 }
643 return outlen;
644 }
645
646 /**
647 * See header
648 */
649 #undef read
650 ssize_t windows_read(int fd, void *buf, size_t count)
651 {
652 ssize_t ret;
653
654 ret = wserr(recv(fd, buf, count, 0));
655 if (ret == -1 && errno == ENOTSOCK)
656 {
657 ret = read(fd, buf, count);
658 }
659 return ret;
660 }
661
662 /**
663 * See header
664 */
665 #undef write
666 ssize_t windows_write(int fd, void *buf, size_t count)
667 {
668 ssize_t ret;
669
670 ret = wserr(send(fd, buf, count, 0));
671 if (ret == -1 && errno == ENOTSOCK)
672 {
673 ret = write(fd, buf, count);
674 }
675 return ret;
676 }
677
678 /**
679 * See header
680 */
681 int poll(struct pollfd *fds, int nfds, int timeout)
682 {
683 return wserr(WSAPoll(fds, nfds, timeout));
684 }