Annotation of embedaddon/strongswan/src/libstrongswan/utils/compat/windows.c, revision 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>