Annotation of embedaddon/strongswan/src/libcharon/plugins/socket_win/socket_win_socket.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: /* for WSAID_WSASENDMSG, Windows 7 */
! 17: #define _WIN32_WINNT 0x0601
! 18:
! 19: #include "socket_win_socket.h"
! 20:
! 21: #include <library.h>
! 22: #include <threading/thread.h>
! 23: #include <daemon.h>
! 24:
! 25: #include <mswsock.h>
! 26:
! 27: /* number of sockets in use */
! 28: #define SOCKET_COUNT 2
! 29:
! 30: /* missing on MinGW */
! 31: #ifndef IPV6_V6ONLY
! 32: # define IPV6_V6ONLY 27
! 33: #endif
! 34:
! 35: /* GUIDS to lookup WSASend/RecvMsg */
! 36: static GUID WSARecvMsgGUID = WSAID_WSARECVMSG;
! 37: static GUID WSASendMsgGUID = WSAID_WSASENDMSG;
! 38:
! 39: typedef struct private_socket_win_socket_t private_socket_win_socket_t;
! 40:
! 41: /**
! 42: * Private data of an socket_t object
! 43: */
! 44: struct private_socket_win_socket_t {
! 45:
! 46: /**
! 47: * public functions
! 48: */
! 49: socket_win_socket_t public;
! 50:
! 51: /**
! 52: * Port for each socket
! 53: */
! 54: uint16_t ports[SOCKET_COUNT];
! 55:
! 56: /**
! 57: * IPv4/IPv6 dual-use sockets
! 58: */
! 59: SOCKET socks[SOCKET_COUNT];
! 60:
! 61: /**
! 62: * Events to wait for socket data
! 63: */
! 64: HANDLE events[SOCKET_COUNT];
! 65:
! 66: /**
! 67: * Maximum packet size to receive
! 68: */
! 69: int max_packet;
! 70:
! 71: /**
! 72: * WSASendMsg function
! 73: */
! 74: int WINAPI (*WSASendMsg)(SOCKET, LPWSAMSG, DWORD, LPDWORD,
! 75: LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
! 76:
! 77: /**
! 78: * WSARecvMsg function
! 79: */
! 80: int WINAPI (*WSARecvMsg)(SOCKET, LPWSAMSG, LPDWORD,
! 81: LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
! 82: };
! 83:
! 84: METHOD(socket_t, receiver, status_t,
! 85: private_socket_win_socket_t *this, packet_t **out)
! 86: {
! 87: char buf[this->max_packet], cbuf[128];
! 88: bool old;
! 89: DWORD i, len, err;
! 90: WSAMSG msg;
! 91: WSABUF data;
! 92: WSACMSGHDR *cmsg;
! 93: SOCKADDR_IN6 addr;
! 94: host_t *src = NULL, *dst = NULL;
! 95: packet_t *pkt;
! 96:
! 97: data.buf = buf;
! 98: data.len = sizeof(buf);
! 99:
! 100: memset(&msg, 0, sizeof(msg));
! 101: msg.name = (struct sockaddr*)&addr;
! 102: msg.namelen = sizeof(addr);
! 103: msg.lpBuffers = &data;
! 104: msg.dwBufferCount = 1;
! 105: msg.Control.buf = cbuf;
! 106: msg.Control.len = sizeof(cbuf);
! 107:
! 108: /* wait for socket events */
! 109: old = thread_cancelability(TRUE);
! 110: i = WSAWaitForMultipleEvents(SOCKET_COUNT, this->events,
! 111: FALSE, INFINITE, TRUE);
! 112: thread_cancelability(old);
! 113: if (i < WSA_WAIT_EVENT_0 || i >= WSA_WAIT_EVENT_0 + SOCKET_COUNT)
! 114: {
! 115: DBG1(DBG_NET, "waiting on sockets failed: %d", WSAGetLastError());
! 116: return FAILED;
! 117: }
! 118: i -= WSA_WAIT_EVENT_0;
! 119:
! 120: /* WSAEvents must be reset manually */
! 121: WSAResetEvent(this->events[i]);
! 122:
! 123: if (this->WSARecvMsg(this->socks[i], &msg, &len,
! 124: NULL, NULL) == SOCKET_ERROR)
! 125: {
! 126: err = WSAGetLastError();
! 127: /* ignore WSAECONNRESET; this is returned for any ICMP port unreachable,
! 128: * for a packet we sent, but is most likely not related to the packet
! 129: * we try to receive. */
! 130: if (err != WSAECONNRESET)
! 131: {
! 132: DBG1(DBG_NET, "reading from socket failed: %d", WSAGetLastError());
! 133: }
! 134: return FAILED;
! 135: }
! 136:
! 137: DBG3(DBG_NET, "received packet %b", buf, (int)len);
! 138:
! 139: for (cmsg = WSA_CMSG_FIRSTHDR(&msg); dst == NULL && cmsg != NULL;
! 140: cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
! 141: {
! 142: if (cmsg->cmsg_level == IPPROTO_IP &&
! 143: cmsg->cmsg_type == IP_PKTINFO)
! 144: {
! 145: struct in_pktinfo *pktinfo;
! 146: struct sockaddr_in sin = {
! 147: .sin_family = AF_INET,
! 148: };
! 149:
! 150: pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
! 151: sin.sin_addr = pktinfo->ipi_addr;
! 152: sin.sin_port = htons(this->ports[i]);
! 153: dst = host_create_from_sockaddr((struct sockaddr*)&sin);
! 154: }
! 155: if (cmsg->cmsg_level == IPPROTO_IPV6 &&
! 156: cmsg->cmsg_type == IPV6_PKTINFO)
! 157: {
! 158: struct in6_pktinfo *pktinfo;
! 159: struct sockaddr_in6 sin = {
! 160: .sin6_family = AF_INET6,
! 161: };
! 162:
! 163: pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
! 164: sin.sin6_addr = pktinfo->ipi6_addr;
! 165: sin.sin6_port = htons(this->ports[i]);
! 166: dst = host_create_from_sockaddr((struct sockaddr*)&sin);
! 167: }
! 168: }
! 169:
! 170: if (!dst)
! 171: {
! 172: DBG1(DBG_NET, "receiving IP destination address failed");
! 173: return FAILED;
! 174: }
! 175:
! 176: switch (dst->get_family(dst))
! 177: {
! 178: case AF_INET6:
! 179: src = host_create_from_sockaddr((struct sockaddr*)&addr);
! 180: break;
! 181: case AF_INET:
! 182: /* extract v4 address from mapped v6 */
! 183: src = host_create_from_chunk(AF_INET,
! 184: chunk_create(addr.sin6_addr.u.Byte + 12, 4),
! 185: ntohs(addr.sin6_port));
! 186: break;
! 187: }
! 188: if (!src)
! 189: {
! 190: DBG1(DBG_NET, "receiving IP source address failed");
! 191: dst->destroy(dst);
! 192: return FAILED;
! 193: }
! 194:
! 195: pkt = packet_create();
! 196: pkt->set_source(pkt, src);
! 197: pkt->set_destination(pkt, dst);
! 198: DBG2(DBG_NET, "received packet: from %#H to %#H", src, dst);
! 199: pkt->set_data(pkt, chunk_clone(chunk_create(buf, len)));
! 200:
! 201: *out = pkt;
! 202: return SUCCESS;
! 203: }
! 204:
! 205: METHOD(socket_t, sender, status_t,
! 206: private_socket_win_socket_t *this, packet_t *packet)
! 207: {
! 208: uint16_t port;
! 209: int i = -1, j;
! 210: host_t *src, *dst;
! 211: WSAMSG msg;
! 212: DWORD len;
! 213: WSABUF data;
! 214: WSACMSGHDR *cmsg;
! 215: SOCKADDR_IN6 addr = {
! 216: .sin6_family = AF_INET6,
! 217: .sin6_addr = {
! 218: .u = {
! 219: .Byte = {
! 220: /* v6-mapped-v4 by default */
! 221: 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
! 222: 0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
! 223: },
! 224: },
! 225: },
! 226: };
! 227: char buf[WSA_CMSG_SPACE(max(sizeof(struct in6_pktinfo),
! 228: sizeof(struct in_pktinfo)))];
! 229:
! 230: src = packet->get_source(packet);
! 231: dst = packet->get_destination(packet);
! 232: data.len = packet->get_data(packet).len;
! 233: data.buf = packet->get_data(packet).ptr;
! 234:
! 235: DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
! 236:
! 237: DBG3(DBG_NET, "sending packet %b", data.buf, (int)data.len);
! 238:
! 239: port = src->get_port(src);
! 240: for (j = 0; j < SOCKET_COUNT; j++)
! 241: {
! 242: if (!port || this->ports[j] == port)
! 243: {
! 244: i = j;
! 245: break;
! 246: }
! 247: }
! 248: if (i == -1)
! 249: {
! 250: DBG1(DBG_NET, "no socket found to send packet from port %u", port);
! 251: return FAILED;
! 252: }
! 253:
! 254: /* copy destination IPv6, or last 32 bits of mapped IPv4 address */
! 255: len = dst->get_address(dst).len;
! 256: if (len > sizeof(addr.sin6_addr))
! 257: {
! 258: return FAILED;
! 259: }
! 260: memcpy(addr.sin6_addr.u.Byte + sizeof(addr.sin6_addr) - len,
! 261: dst->get_address(dst).ptr, len);
! 262: addr.sin6_port = htons(dst->get_port(dst));
! 263:
! 264: memset(&msg, 0, sizeof(msg));
! 265: msg.name = (struct sockaddr*)&addr;
! 266: msg.namelen = sizeof(addr);
! 267: msg.lpBuffers = &data;
! 268: msg.dwBufferCount = 1;
! 269:
! 270: if (!src->is_anyaddr(src))
! 271: {
! 272: memset(buf, 0, sizeof(buf));
! 273: msg.Control.buf = buf;
! 274:
! 275: switch (src->get_family(src))
! 276: {
! 277: case AF_INET:
! 278: {
! 279: struct in_pktinfo *pktinfo;
! 280: SOCKADDR_IN *sin;
! 281:
! 282: msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
! 283: cmsg = WSA_CMSG_FIRSTHDR(&msg);
! 284: cmsg->cmsg_level = IPPROTO_IP;
! 285: cmsg->cmsg_type = IP_PKTINFO;
! 286: cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
! 287: pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
! 288: sin = (SOCKADDR_IN*)src->get_sockaddr(src);
! 289: pktinfo->ipi_addr = sin->sin_addr;
! 290: break;
! 291: }
! 292: case AF_INET6:
! 293: {
! 294: struct in6_pktinfo *pktinfo;
! 295: SOCKADDR_IN6 *sin;
! 296:
! 297: msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
! 298: cmsg = WSA_CMSG_FIRSTHDR(&msg);
! 299: cmsg->cmsg_level = IPPROTO_IPV6;
! 300: cmsg->cmsg_type = IPV6_PKTINFO;
! 301: cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
! 302: pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
! 303: sin = (SOCKADDR_IN6*)src->get_sockaddr(src);
! 304: pktinfo->ipi6_addr = sin->sin6_addr;
! 305: break;
! 306: }
! 307: }
! 308: }
! 309:
! 310: if (this->WSASendMsg(this->socks[i], &msg, 0, &len,
! 311: NULL, NULL) == SOCKET_ERROR)
! 312: {
! 313: DBG1(DBG_NET, "sending packet failed: %d", WSAGetLastError());
! 314: return FAILED;
! 315: }
! 316: return SUCCESS;
! 317: }
! 318:
! 319: METHOD(socket_t, get_port, uint16_t,
! 320: private_socket_win_socket_t *this, bool nat)
! 321: {
! 322: return this->ports[nat != 0];
! 323: }
! 324:
! 325: METHOD(socket_t, supported_families, socket_family_t,
! 326: private_socket_win_socket_t *this)
! 327: {
! 328: return SOCKET_FAMILY_IPV4 | SOCKET_FAMILY_IPV6;
! 329: }
! 330:
! 331: /**
! 332: * Open an IPv4/IPv6 dual-use socket to send and receive packets
! 333: */
! 334: static SOCKET open_socket(private_socket_win_socket_t *this, int i)
! 335: {
! 336: SOCKADDR_IN6 addr = {
! 337: .sin6_family = AF_INET6,
! 338: .sin6_port = htons(this->ports[i]),
! 339: };
! 340: int addrlen = sizeof(addr);
! 341: BOOL on = TRUE, off = FALSE;
! 342: DWORD dwon = TRUE;
! 343: SOCKET s;
! 344:
! 345: s = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
! 346: if (s == INVALID_SOCKET)
! 347: {
! 348: DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
! 349: return INVALID_SOCKET;
! 350: }
! 351: /* enable IPv4 on IPv6 socket */
! 352: if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
! 353: (const char*)&off, sizeof(off)) == SOCKET_ERROR)
! 354: {
! 355: DBG1(DBG_NET, "using dual-mode socket failed: %d", WSAGetLastError());
! 356: closesocket(s);
! 357: return INVALID_SOCKET;
! 358: }
! 359: if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
! 360: (const char*)&on, sizeof(on)) == SOCKET_ERROR)
! 361: {
! 362: DBG1(DBG_NET, "enabling SO_REUSEADDR failed: %d", WSAGetLastError());
! 363: closesocket(s);
! 364: return INVALID_SOCKET;
! 365: }
! 366: if (bind(s, (const struct sockaddr*)&addr, addrlen) == SOCKET_ERROR)
! 367: {
! 368: DBG1(DBG_NET, "unable to bind socket: %d", WSAGetLastError());
! 369: closesocket(s);
! 370: return INVALID_SOCKET;
! 371: }
! 372: /* retrieve randomly allocated port if needed */
! 373: if (this->ports[i] == 0)
! 374: {
! 375: if (getsockname(s, (struct sockaddr*)&addr,
! 376: &addrlen) == SOCKET_ERROR)
! 377: {
! 378: DBG1(DBG_NET, "unable to determine port: %d", WSAGetLastError());
! 379: closesocket(s);
! 380: return INVALID_SOCKET;
! 381: }
! 382: this->ports[i] = ntohs(addr.sin6_port);
! 383: }
! 384: /* PKTINFO is required for both protocol families */
! 385: if (setsockopt(s, IPPROTO_IP, IP_PKTINFO,
! 386: (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
! 387: {
! 388: DBG1(DBG_NET, "unable to set IP_PKTINFO: %d", WSAGetLastError());
! 389: closesocket(s);
! 390: return INVALID_SOCKET;
! 391: }
! 392: if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
! 393: (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
! 394: {
! 395: DBG1(DBG_NET, "unable to set IP6_PKTINFO: %d", WSAGetLastError());
! 396: closesocket(s);
! 397: return INVALID_SOCKET;
! 398: }
! 399: if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET))
! 400: {
! 401: DBG1(DBG_NET, "installing IPv4 IKE bypass policy failed");
! 402: }
! 403: if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET6))
! 404: {
! 405: DBG1(DBG_NET, "installing IPv6 IKE bypass policy failed");
! 406: }
! 407: return s;
! 408: }
! 409:
! 410: METHOD(socket_t, destroy, void,
! 411: private_socket_win_socket_t *this)
! 412: {
! 413: int i;
! 414:
! 415: for (i = 0; i < SOCKET_COUNT; i++)
! 416: {
! 417: if (this->socks[i] != INVALID_SOCKET)
! 418: {
! 419: closesocket(this->socks[i]);
! 420: }
! 421: if (this->events[i] != WSA_INVALID_EVENT)
! 422: {
! 423: WSACloseEvent(this->events[i]);
! 424: }
! 425: }
! 426: free(this);
! 427: }
! 428:
! 429: /*
! 430: * See header for description
! 431: */
! 432: socket_win_socket_t *socket_win_socket_create()
! 433: {
! 434: private_socket_win_socket_t *this;
! 435: DWORD len;
! 436: int i;
! 437:
! 438: INIT(this,
! 439: .public = {
! 440: .socket = {
! 441: .send = _sender,
! 442: .receive = _receiver,
! 443: .get_port = _get_port,
! 444: .supported_families = _supported_families,
! 445: .destroy = _destroy,
! 446: },
! 447: },
! 448: .ports = {
! 449: lib->settings->get_int(lib->settings,
! 450: "%s.port", CHARON_UDP_PORT, lib->ns),
! 451: lib->settings->get_int(lib->settings,
! 452: "%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
! 453: },
! 454: .max_packet = lib->settings->get_int(lib->settings,
! 455: "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
! 456: );
! 457:
! 458: for (i = 0; i < SOCKET_COUNT; i++)
! 459: {
! 460: this->socks[i] = open_socket(this, i);
! 461: this->events[i] = WSACreateEvent();
! 462: }
! 463:
! 464: for (i = 0; i < SOCKET_COUNT; i++)
! 465: {
! 466: if (this->events[i] == WSA_INVALID_EVENT ||
! 467: this->socks[i] == INVALID_SOCKET)
! 468: {
! 469: DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
! 470: destroy(this);
! 471: return NULL;
! 472: }
! 473: if (WSAEventSelect(this->socks[i], this->events[i],
! 474: FD_READ) == SOCKET_ERROR)
! 475: {
! 476: DBG1(DBG_NET, "WSAEventSelect() failed: %d", WSAGetLastError());
! 477: destroy(this);
! 478: return NULL;
! 479: }
! 480: }
! 481:
! 482: if (WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
! 483: &WSASendMsgGUID, sizeof(WSASendMsgGUID), &this->WSASendMsg,
! 484: sizeof(this->WSASendMsg), &len, NULL, NULL) != 0 ||
! 485: WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
! 486: &WSARecvMsgGUID, sizeof(WSARecvMsgGUID), &this->WSARecvMsg,
! 487: sizeof(this->WSARecvMsg), &len, NULL, NULL) != 0)
! 488: {
! 489: DBG1(DBG_NET, "send/recvmsg() lookup failed: %d", WSAGetLastError());
! 490: destroy(this);
! 491: return NULL;
! 492: }
! 493:
! 494: return &this->public;
! 495: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>