2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
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>.
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
16 /* for WSAID_WSASENDMSG, Windows 7 */
17 #define _WIN32_WINNT 0x0601
19 #include "socket_win_socket.h"
22 #include <threading/thread.h>
27 /* number of sockets in use */
28 #define SOCKET_COUNT 2
30 /* missing on MinGW */
32 # define IPV6_V6ONLY 27
35 /* GUIDS to lookup WSASend/RecvMsg */
36 static GUID WSARecvMsgGUID
= WSAID_WSARECVMSG
;
37 static GUID WSASendMsgGUID
= WSAID_WSASENDMSG
;
39 typedef struct private_socket_win_socket_t private_socket_win_socket_t
;
42 * Private data of an socket_t object
44 struct private_socket_win_socket_t
{
49 socket_win_socket_t
public;
52 * Port for each socket
54 u_int16_t ports
[SOCKET_COUNT
];
57 * IPv4/IPv6 dual-use sockets
59 SOCKET socks
[SOCKET_COUNT
];
62 * Events to wait for socket data
64 HANDLE events
[SOCKET_COUNT
];
67 * Maximum packet size to receive
74 int WINAPI (*WSASendMsg
)(SOCKET
, LPWSAMSG
, DWORD
, LPDWORD
,
75 LPWSAOVERLAPPED
, LPWSAOVERLAPPED_COMPLETION_ROUTINE
);
80 int WINAPI (*WSARecvMsg
)(SOCKET
, LPWSAMSG
, LPDWORD
,
81 LPWSAOVERLAPPED
, LPWSAOVERLAPPED_COMPLETION_ROUTINE
);
84 METHOD(socket_t
, receiver
, status_t
,
85 private_socket_win_socket_t
*this, packet_t
**out
)
87 char buf
[this->max_packet
], cbuf
[128];
94 host_t
*src
= NULL
, *dst
= NULL
;
98 data
.len
= sizeof(buf
);
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
);
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
)
115 DBG1(DBG_NET
, "waiting on sockets failed: %d", WSAGetLastError());
118 i
-= WSA_WAIT_EVENT_0
;
120 /* WSAEvents must be reset manually */
121 WSAResetEvent(this->events
[i
]);
123 if (this->WSARecvMsg(this->socks
[i
], &msg
, &len
,
124 NULL
, NULL
) == SOCKET_ERROR
)
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
)
132 DBG1(DBG_NET
, "reading from socket failed: %d", WSAGetLastError());
137 DBG3(DBG_NET
, "received packet %b", buf
, (int)len
);
139 for (cmsg
= WSA_CMSG_FIRSTHDR(&msg
); dst
== NULL
&& cmsg
!= NULL
;
140 cmsg
= WSA_CMSG_NXTHDR(&msg
, cmsg
))
142 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
143 cmsg
->cmsg_type
== IP_PKTINFO
)
145 struct in_pktinfo
*pktinfo
;
146 struct sockaddr_in sin
= {
147 .sin_family
= AF_INET
,
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
);
155 if (cmsg
->cmsg_level
== IPPROTO_IPV6
&&
156 cmsg
->cmsg_type
== IPV6_PKTINFO
)
158 struct in6_pktinfo
*pktinfo
;
159 struct sockaddr_in6 sin
= {
160 .sin6_family
= AF_INET6
,
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
);
172 DBG1(DBG_NET
, "receiving IP destination address failed");
176 switch (dst
->get_family(dst
))
179 src
= host_create_from_sockaddr((struct sockaddr
*)&addr
);
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
));
190 DBG1(DBG_NET
, "receiving IP source address failed");
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
)));
205 METHOD(socket_t
, sender
, status_t
,
206 private_socket_win_socket_t
*this, packet_t
*packet
)
215 SOCKADDR_IN6 addr
= {
216 .sin6_family
= AF_INET6
,
220 /* v6-mapped-v4 by default */
221 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222 0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
227 char buf
[WSA_CMSG_SPACE(max(sizeof(struct in6_pktinfo
),
228 sizeof(struct in_pktinfo
)))];
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
;
235 DBG2(DBG_NET
, "sending packet: from %#H to %#H", src
, dst
);
237 DBG3(DBG_NET
, "sending packet %b", data
.buf
, (int)data
.len
);
239 port
= src
->get_port(src
);
240 for (j
= 0; j
< SOCKET_COUNT
; j
++)
242 if (!port
|| this->ports
[j
] == port
)
250 DBG1(DBG_NET
, "no socket found to send packet from port %u", port
);
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
))
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
));
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;
270 if (!src
->is_anyaddr(src
))
272 memset(buf
, 0, sizeof(buf
));
273 msg
.Control
.buf
= buf
;
275 switch (src
->get_family(src
))
279 struct in_pktinfo
*pktinfo
;
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
;
294 struct in6_pktinfo
*pktinfo
;
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
;
310 if (this->WSASendMsg(this->socks
[i
], &msg
, 0, &len
,
311 NULL
, NULL
) == SOCKET_ERROR
)
313 DBG1(DBG_NET
, "sending packet failed: %d", WSAGetLastError());
319 METHOD(socket_t
, get_port
, u_int16_t
,
320 private_socket_win_socket_t
*this, bool nat
)
322 return this->ports
[nat
!= 0];
325 METHOD(socket_t
, supported_families
, socket_family_t
,
326 private_socket_win_socket_t
*this)
328 return SOCKET_FAMILY_IPV4
| SOCKET_FAMILY_IPV6
;
332 * Open an IPv4/IPv6 dual-use socket to send and receive packets
334 static SOCKET
open_socket(private_socket_win_socket_t
*this, int i
)
336 SOCKADDR_IN6 addr
= {
337 .sin6_family
= AF_INET6
,
338 .sin6_port
= htons(this->ports
[i
]),
340 int addrlen
= sizeof(addr
);
341 BOOL on
= TRUE
, off
= FALSE
;
345 s
= WSASocket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, NULL
, 0, 0);
346 if (s
== INVALID_SOCKET
)
348 DBG1(DBG_NET
, "creating socket failed: %d", WSAGetLastError());
349 return INVALID_SOCKET
;
351 /* enable IPv4 on IPv6 socket */
352 if (setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
353 (const char*)&off
, sizeof(off
)) == SOCKET_ERROR
)
355 DBG1(DBG_NET
, "using dual-mode socket failed: %d", WSAGetLastError());
357 return INVALID_SOCKET
;
359 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
,
360 (const char*)&on
, sizeof(on
)) == SOCKET_ERROR
)
362 DBG1(DBG_NET
, "enabling SO_REUSEADDR failed: %d", WSAGetLastError());
364 return INVALID_SOCKET
;
366 if (bind(s
, (const struct sockaddr
*)&addr
, addrlen
) == SOCKET_ERROR
)
368 DBG1(DBG_NET
, "unable to bind socket: %d", WSAGetLastError());
370 return INVALID_SOCKET
;
372 /* retrieve randomly allocated port if needed */
373 if (this->ports
[i
] == 0)
375 if (getsockname(s
, (struct sockaddr
*)&addr
,
376 &addrlen
) == SOCKET_ERROR
)
378 DBG1(DBG_NET
, "unable to determine port: %d", WSAGetLastError());
380 return INVALID_SOCKET
;
382 this->ports
[i
] = ntohs(addr
.sin6_port
);
384 /* PKTINFO is required for both protocol families */
385 if (setsockopt(s
, IPPROTO_IP
, IP_PKTINFO
,
386 (char*)&dwon
, sizeof(dwon
)) == SOCKET_ERROR
)
388 DBG1(DBG_NET
, "unable to set IP_PKTINFO: %d", WSAGetLastError());
390 return INVALID_SOCKET
;
392 if (setsockopt(s
, IPPROTO_IPV6
, IPV6_PKTINFO
,
393 (char*)&dwon
, sizeof(dwon
)) == SOCKET_ERROR
)
395 DBG1(DBG_NET
, "unable to set IP6_PKTINFO: %d", WSAGetLastError());
397 return INVALID_SOCKET
;
399 if (!charon
->kernel
->bypass_socket(charon
->kernel
, s
, AF_INET
))
401 DBG1(DBG_NET
, "installing IPv4 IKE bypass policy failed");
403 if (!charon
->kernel
->bypass_socket(charon
->kernel
, s
, AF_INET6
))
405 DBG1(DBG_NET
, "installing IPv6 IKE bypass policy failed");
410 METHOD(socket_t
, destroy
, void,
411 private_socket_win_socket_t
*this)
415 for (i
= 0; i
< SOCKET_COUNT
; i
++)
417 if (this->socks
[i
] != INVALID_SOCKET
)
419 closesocket(this->socks
[i
]);
421 if (this->events
[i
] != WSA_INVALID_EVENT
)
423 WSACloseEvent(this->events
[i
]);
430 * See header for description
432 socket_win_socket_t
*socket_win_socket_create()
434 private_socket_win_socket_t
*this;
442 .receive
= _receiver
,
443 .get_port
= _get_port
,
444 .supported_families
= _supported_families
,
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
),
454 .max_packet
= lib
->settings
->get_int(lib
->settings
,
455 "%s.max_packet", PACKET_MAX_DEFAULT
, lib
->ns
),
458 for (i
= 0; i
< SOCKET_COUNT
; i
++)
460 this->socks
[i
] = open_socket(this, i
);
461 this->events
[i
] = WSACreateEvent();
464 for (i
= 0; i
< SOCKET_COUNT
; i
++)
466 if (this->events
[i
] == WSA_INVALID_EVENT
||
467 this->socks
[i
] == INVALID_SOCKET
)
469 DBG1(DBG_NET
, "creating socket failed: %d", WSAGetLastError());
473 if (WSAEventSelect(this->socks
[i
], this->events
[i
],
474 FD_READ
) == SOCKET_ERROR
)
476 DBG1(DBG_NET
, "WSAEventSelect() failed: %d", WSAGetLastError());
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)
489 DBG1(DBG_NET
, "send/recvmsg() lookup failed: %d", WSAGetLastError());
494 return &this->public;