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