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