windows: Fix off-by-one error in strerror_s_extended()
[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(s);
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 * See header
255 */
256 char* getpass(const char *prompt)
257 {
258 static char buf[64] = "";
259 char *pos;
260 HANDLE in, out;
261 DWORD mode, written = 0, total, done;
262
263 out = GetStdHandle(STD_OUTPUT_HANDLE);
264 in = GetStdHandle(STD_INPUT_HANDLE);
265
266 if (out == INVALID_HANDLE_VALUE || in == INVALID_HANDLE_VALUE ||
267 !GetConsoleMode(out, &mode) || !GetConsoleMode(in, &mode))
268 {
269 return NULL;
270 }
271
272 total = strlen(prompt);
273 while (written < total)
274 {
275 if (!WriteConsole(out, prompt + written, total - written, &done, NULL))
276 {
277 return NULL;
278 }
279 written += done;
280 }
281
282 if (!SetConsoleMode(in, mode & ~ENABLE_ECHO_INPUT))
283 {
284 return NULL;
285 }
286
287 while (TRUE)
288 {
289 if (!ReadConsole(in, buf, sizeof(buf), &done, NULL))
290 {
291 SetConsoleMode(in, mode);
292 return NULL;
293 }
294 buf[sizeof(buf)-1] = '\0';
295
296 if (done)
297 {
298 pos = strchr(buf, '\r');
299 if (pos)
300 {
301 *pos = '\0';
302 }
303 break;
304 }
305 }
306 SetConsoleMode(in, mode);
307
308 /* append a newline, as we have no echo during input */
309 WriteConsole(out, "\r\n", 2, &done, NULL);
310
311 return buf;
312 }
313
314 /**
315 * See header.
316 */
317 #undef strerror_s
318 int strerror_s_extended(char *buf, size_t buflen, int errnum)
319 {
320 const char *errstr [] = {
321 /* EADDRINUSE */ "Address in use",
322 /* EADDRNOTAVAIL */ "Address not available",
323 /* EAFNOSUPPORT */ "Address family not supported",
324 /* EALREADY */ "Connection already in progress",
325 /* EBADMSG */ "Bad message",
326 /* ECANCELED */ "Operation canceled",
327 /* ECONNABORTED */ "Connection aborted",
328 /* ECONNREFUSED */ "Connection refused",
329 /* ECONNRESET */ "Connection reset",
330 /* EDESTADDRREQ */ "Destination address required",
331 /* EHOSTUNREACH */ "Host is unreachable",
332 /* EIDRM */ "Identifier removed",
333 /* EINPROGRESS */ "Operation in progress",
334 /* EISCONN */ "Socket is connected",
335 /* ELOOP */ "Too many levels of symbolic links",
336 /* EMSGSIZE */ "Message too large",
337 /* ENETDOWN */ "Network is down",
338 /* ENETRESET */ "Connection aborted by network",
339 /* ENETUNREACH */ "Network unreachable",
340 /* ENOBUFS */ "No buffer space available",
341 /* ENODATA */ "No message is available",
342 /* ENOLINK */ "No link",
343 /* ENOMSG */ "No message of the desired type",
344 /* ENOPROTOOPT */ "Protocol not available",
345 /* ENOSR */ "No stream resources",
346 /* ENOSTR */ "Not a stream",
347 /* ENOTCONN */ "The socket is not connected",
348 /* ENOTRECOVERABLE */ "State not recoverable",
349 /* ENOTSOCK */ "Not a socket",
350 /* ENOTSUP */ "Not supported",
351 /* EOPNOTSUPP */ "Operation not supported on socket",
352 /* EOTHER */ "Other error",
353 /* EOVERFLOW */ "Value too large to be stored in data type",
354 /* EOWNERDEAD */ "Previous owner died",
355 /* EPROTO */ "Protocol error",
356 /* EPROTONOSUPPORT */ "Protocol not supported",
357 /* EPROTOTYPE */ "Protocol wrong type for socket",
358 /* ETIME */ "Timeout",
359 /* ETIMEDOUT */ "Connection timed out",
360 /* ETXTBSY */ "Text file busy",
361 /* EWOULDBLOCK */ "Operation would block",
362 };
363 int offset = EADDRINUSE;
364
365 if (errnum < offset || errnum >= offset + countof(errstr))
366 {
367 return strerror_s(buf, buflen, errnum);
368 }
369 strncpy(buf, errstr[errnum - offset], buflen);
370 buf[buflen - 1] = '\0';
371 return 0;
372 }
373
374 /**
375 * Set errno for a function setting WSA error on failure
376 */
377 static int wserr(int retval)
378 {
379 if (retval < 0)
380 {
381 static const struct {
382 DWORD wsa;
383 int err;
384 } map[] = {
385 { WSANOTINITIALISED, EBADF },
386 { WSAENETDOWN, ENETDOWN },
387 { WSAENETRESET, ENETRESET },
388 { WSAECONNABORTED, ECONNABORTED },
389 { WSAESHUTDOWN, ECONNABORTED },
390 { WSAEACCES, EACCES },
391 { WSAEINTR, EINTR },
392 { WSAEINPROGRESS, EINPROGRESS },
393 { WSAEFAULT, EFAULT },
394 { WSAENOBUFS, ENOBUFS },
395 { WSAENOTSOCK, ENOTSOCK },
396 { WSAEOPNOTSUPP, EOPNOTSUPP },
397 { WSAEWOULDBLOCK, EWOULDBLOCK },
398 { WSAEMSGSIZE, EMSGSIZE },
399 { WSAEINVAL, EINVAL },
400 { WSAENOTCONN, ENOTCONN },
401 { WSAEHOSTUNREACH, EHOSTUNREACH },
402 { WSAENETUNREACH, ENETUNREACH },
403 { WSAECONNABORTED, ECONNABORTED },
404 { WSAECONNRESET, ECONNRESET },
405 { WSAETIMEDOUT, ETIMEDOUT },
406 { WSAEMFILE, EMFILE },
407 { WSAEALREADY, EALREADY },
408 { WSAEDESTADDRREQ, EDESTADDRREQ },
409 { WSAEISCONN, EISCONN },
410 { WSAEOPNOTSUPP, EOPNOTSUPP },
411 { WSAEPROTOTYPE, EPROTOTYPE },
412 { WSAENOPROTOOPT, ENOPROTOOPT },
413 { WSAEPROTONOSUPPORT, EPROTONOSUPPORT },
414 { WSAEPFNOSUPPORT, EPROTONOSUPPORT },
415 { WSAEAFNOSUPPORT, EAFNOSUPPORT },
416 { WSAEADDRNOTAVAIL, EADDRNOTAVAIL },
417 { WSAEADDRINUSE, EADDRINUSE },
418 { WSAETIMEDOUT, ETIMEDOUT },
419 { WSAECONNREFUSED, ECONNREFUSED },
420 { WSAELOOP, ELOOP },
421 { WSAENAMETOOLONG, ENAMETOOLONG },
422 { WSAENOTEMPTY, ENOTEMPTY },
423 { WSAEPROTOTYPE, EPROTOTYPE },
424 { WSAVERNOTSUPPORTED, ENOTSUP },
425 };
426 DWORD wsa, i;
427
428 wsa = WSAGetLastError();
429 for (i = 0; i < countof(map); i++)
430 {
431 if (map[i].wsa == wsa)
432 {
433 errno = map[i].err;
434 return retval;
435 }
436 }
437 errno = ENOENT;
438 return retval;
439 }
440 errno = 0;
441 return retval;
442 }
443
444 /**
445 * Check and clear the dontwait flag
446 */
447 static bool check_dontwait(int *flags)
448 {
449 if (*flags & MSG_DONTWAIT)
450 {
451 *flags &= ~MSG_DONTWAIT;
452 return TRUE;
453 }
454 return FALSE;
455 }
456
457 /**
458 * See header
459 */
460 #undef shutdown
461 int windows_shutdown(int sockfd, int how)
462 {
463 return wserr(shutdown(sockfd, how));
464 }
465
466 /**
467 * See header
468 */
469 #undef accept
470 int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
471 {
472 return wserr(accept(sockfd, addr, addrlen));
473 }
474
475 /**
476 * See header
477 */
478 #undef bind
479 int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
480 {
481 return wserr(bind(sockfd, addr, addrlen));
482 }
483
484 /**
485 * See header
486 */
487 #undef connect
488 int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
489 {
490 return wserr(connect(sockfd, addr, addrlen));
491 }
492
493 /**
494 * See header
495 */
496 #undef getsockname
497 int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
498 {
499 return wserr(getsockname(sockfd, addr, addrlen));
500 }
501
502 /**
503 * See header
504 */
505 #undef getsockopt
506 int windows_getsockopt(int sockfd, int level, int optname,
507 void *optval, socklen_t *optlen)
508 {
509 return wserr(getsockopt(sockfd, level, optname, optval, optlen));
510 }
511
512 /**
513 * See header
514 */
515 #undef setsockopt
516 int windows_setsockopt(int sockfd, int level, int optname,
517 const void *optval, socklen_t optlen)
518 {
519 return wserr(setsockopt(sockfd, level, optname, optval, optlen));
520 }
521
522 /**
523 * See header
524 */
525 #undef socket
526 int windows_socket(int domain, int type, int protocol)
527 {
528 return wserr(socket(domain, type, protocol));
529 }
530
531 /**
532 * See header
533 */
534 #undef select
535 int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
536 fd_set *exceptfds, struct timeval *timeout)
537 {
538 return wserr(select(nfds, readfds, writefds, exceptfds, timeout));
539 }
540
541 /**
542 * See header
543 */
544 #undef close
545 int windows_close(int fd)
546 {
547 int ret;
548
549 ret = close(fd);
550 if (ret == -1 && errno == EBADF)
551 { /* Winsock socket? */
552 ret = wserr(closesocket(fd));
553 }
554 return ret;
555 }
556
557 /**
558 * See header
559 */
560 #undef recv
561 ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags)
562 {
563 u_long on = 1, off = 0;
564 ssize_t outlen = -1;
565
566 if (!check_dontwait(&flags))
567 {
568 return wserr(recv(sockfd, buf, len, flags));
569 }
570 if (wserr(ioctlsocket(sockfd, FIONBIO, &on) == 0))
571 {
572 outlen = wserr(recv(sockfd, buf, len, flags));
573 ioctlsocket(sockfd, FIONBIO, &off);
574 }
575 return outlen;
576 }
577
578 /**
579 * See header
580 */
581 #undef recvfrom
582 ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
583 struct sockaddr *src_addr, socklen_t *addrlen)
584 {
585 u_long on = 1, off = 0;
586 ssize_t outlen = -1;
587
588 if (!check_dontwait(&flags))
589 {
590 return wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
591 }
592 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
593 {
594 outlen = wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
595 ioctlsocket(sockfd, FIONBIO, &off);
596 }
597 return outlen;
598 }
599
600 /**
601 * See header
602 */
603 #undef send
604 ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags)
605 {
606 u_long on = 1, off = 0;
607 ssize_t outlen = -1;
608
609 if (!check_dontwait(&flags))
610 {
611 return wserr(send(sockfd, buf, len, flags));
612 }
613 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
614 {
615 outlen = wserr(send(sockfd, buf, len, flags));
616 ioctlsocket(sockfd, FIONBIO, &off);
617 }
618 return outlen;
619 }
620
621 /**
622 * See header
623 */
624 #undef sendto
625 ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
626 const struct sockaddr *dest_addr, socklen_t addrlen)
627 {
628 u_long on = 1, off = 0;
629 ssize_t outlen = -1;
630
631 if (!check_dontwait(&flags))
632 {
633 return wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
634 }
635 if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
636 {
637 outlen = wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
638 ioctlsocket(sockfd, FIONBIO, &off);
639 }
640 return outlen;
641 }