]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/plugins/socket_win/socket_win_socket.c
libhydra: Move kernel interface to libcharon
[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 <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 u_int16_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 u_int16_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, u_int16_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 }