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"
23 #include <threading/thread.h>
28 /* number of sockets in use */
29 #define SOCKET_COUNT 2
31 /* missing on MinGW */
33 # define IPV6_V6ONLY 27
36 /* GUIDS to lookup WSASend/RecvMsg */
37 static GUID WSARecvMsgGUID
= WSAID_WSARECVMSG
;
38 static GUID WSASendMsgGUID
= WSAID_WSASENDMSG
;
40 typedef struct private_socket_win_socket_t private_socket_win_socket_t
;
43 * Private data of an socket_t object
45 struct private_socket_win_socket_t
{
50 socket_win_socket_t
public;
53 * Port for each socket
55 u_int16_t ports
[SOCKET_COUNT
];
58 * IPv4/IPv6 dual-use sockets
60 SOCKET socks
[SOCKET_COUNT
];
63 * Events to wait for socket data
65 HANDLE events
[SOCKET_COUNT
];
68 * Maximum packet size to receive
75 int WINAPI (*WSASendMsg
)(SOCKET
, LPWSAMSG
, DWORD
, LPDWORD
,
76 LPWSAOVERLAPPED
, LPWSAOVERLAPPED_COMPLETION_ROUTINE
);
81 int WINAPI (*WSARecvMsg
)(SOCKET
, LPWSAMSG
, LPDWORD
,
82 LPWSAOVERLAPPED
, LPWSAOVERLAPPED_COMPLETION_ROUTINE
);
85 METHOD(socket_t
, receiver
, status_t
,
86 private_socket_win_socket_t
*this, packet_t
**out
)
88 char buf
[this->max_packet
], cbuf
[128];
95 host_t
*src
= NULL
, *dst
= NULL
;
99 data
.len
= sizeof(buf
);
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
);
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
)
116 DBG1(DBG_NET
, "waiting on sockets failed: %d", WSAGetLastError());
119 i
-= WSA_WAIT_EVENT_0
;
121 /* WSAEvents must be reset manually */
122 WSAResetEvent(this->events
[i
]);
124 if (this->WSARecvMsg(this->socks
[i
], &msg
, &len
,
125 NULL
, NULL
) == SOCKET_ERROR
)
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
)
133 DBG1(DBG_NET
, "reading from socket failed: %d", WSAGetLastError());
138 DBG3(DBG_NET
, "received packet %b", buf
, (int)len
);
140 for (cmsg
= WSA_CMSG_FIRSTHDR(&msg
); dst
== NULL
&& cmsg
!= NULL
;
141 cmsg
= WSA_CMSG_NXTHDR(&msg
, cmsg
))
143 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
144 cmsg
->cmsg_type
== IP_PKTINFO
)
146 struct in_pktinfo
*pktinfo
;
147 struct sockaddr_in sin
= {
148 .sin_family
= AF_INET
,
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
);
156 if (cmsg
->cmsg_level
== IPPROTO_IPV6
&&
157 cmsg
->cmsg_type
== IPV6_PKTINFO
)
159 struct in6_pktinfo
*pktinfo
;
160 struct sockaddr_in6 sin
= {
161 .sin6_family
= AF_INET6
,
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
);
173 DBG1(DBG_NET
, "receiving IP destination address failed");
177 switch (dst
->get_family(dst
))
180 src
= host_create_from_sockaddr((struct sockaddr
*)&addr
);
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
));
191 DBG1(DBG_NET
, "receiving IP source address failed");
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
)));
206 METHOD(socket_t
, sender
, status_t
,
207 private_socket_win_socket_t
*this, packet_t
*packet
)
216 SOCKADDR_IN6 addr
= {
217 .sin6_family
= AF_INET6
,
221 /* v6-mapped-v4 by default */
222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
223 0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
228 char buf
[WSA_CMSG_SPACE(max(sizeof(struct in6_pktinfo
),
229 sizeof(struct in_pktinfo
)))];
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
;
236 DBG2(DBG_NET
, "sending packet: from %#H to %#H", src
, dst
);
238 DBG3(DBG_NET
, "sending packet %b", data
.buf
, (int)data
.len
);
240 port
= src
->get_port(src
);
241 for (j
= 0; j
< SOCKET_COUNT
; j
++)
243 if (!port
|| this->ports
[j
] == port
)
251 DBG1(DBG_NET
, "no socket found to send packet from port %u", port
);
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
))
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
));
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;
271 if (!src
->is_anyaddr(src
))
273 memset(buf
, 0, sizeof(buf
));
274 msg
.Control
.buf
= buf
;
276 switch (src
->get_family(src
))
280 struct in_pktinfo
*pktinfo
;
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
;
295 struct in6_pktinfo
*pktinfo
;
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
;
311 if (this->WSASendMsg(this->socks
[i
], &msg
, 0, &len
,
312 NULL
, NULL
) == SOCKET_ERROR
)
314 DBG1(DBG_NET
, "sending packet failed: %d", WSAGetLastError());
320 METHOD(socket_t
, get_port
, u_int16_t
,
321 private_socket_win_socket_t
*this, bool nat
)
323 return this->ports
[nat
!= 0];
326 METHOD(socket_t
, supported_families
, socket_family_t
,
327 private_socket_win_socket_t
*this)
329 return SOCKET_FAMILY_IPV4
| SOCKET_FAMILY_IPV6
;
333 * Open an IPv4/IPv6 dual-use socket to send and receive packets
335 static SOCKET
open_socket(private_socket_win_socket_t
*this, int i
)
337 SOCKADDR_IN6 addr
= {
338 .sin6_family
= AF_INET6
,
339 .sin6_port
= htons(this->ports
[i
]),
341 int addrlen
= sizeof(addr
);
342 BOOL on
= TRUE
, off
= FALSE
;
346 s
= WSASocket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, NULL
, 0, 0);
347 if (s
== INVALID_SOCKET
)
349 DBG1(DBG_NET
, "creating socket failed: %d", WSAGetLastError());
350 return INVALID_SOCKET
;
352 /* enable IPv4 on IPv6 socket */
353 if (setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
354 (const char*)&off
, sizeof(off
)) == SOCKET_ERROR
)
356 DBG1(DBG_NET
, "using dual-mode socket failed: %d", WSAGetLastError());
358 return INVALID_SOCKET
;
360 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
,
361 (const char*)&on
, sizeof(on
)) == SOCKET_ERROR
)
363 DBG1(DBG_NET
, "enabling SO_REUSEADDR failed: %d", WSAGetLastError());
365 return INVALID_SOCKET
;
367 if (bind(s
, (const struct sockaddr
*)&addr
, addrlen
) == SOCKET_ERROR
)
369 DBG1(DBG_NET
, "unable to bind socket: %d", WSAGetLastError());
371 return INVALID_SOCKET
;
373 /* retrieve randomly allocated port if needed */
374 if (this->ports
[i
] == 0)
376 if (getsockname(s
, (struct sockaddr
*)&addr
,
377 &addrlen
) == SOCKET_ERROR
)
379 DBG1(DBG_NET
, "unable to determine port: %d", WSAGetLastError());
381 return INVALID_SOCKET
;
383 this->ports
[i
] = ntohs(addr
.sin6_port
);
385 /* PKTINFO is required for both protocol families */
386 if (setsockopt(s
, IPPROTO_IP
, IP_PKTINFO
,
387 (char*)&dwon
, sizeof(dwon
)) == SOCKET_ERROR
)
389 DBG1(DBG_NET
, "unable to set IP_PKTINFO: %d", WSAGetLastError());
391 return INVALID_SOCKET
;
393 if (setsockopt(s
, IPPROTO_IPV6
, IPV6_PKTINFO
,
394 (char*)&dwon
, sizeof(dwon
)) == SOCKET_ERROR
)
396 DBG1(DBG_NET
, "unable to set IP6_PKTINFO: %d", WSAGetLastError());
398 return INVALID_SOCKET
;
400 if (!hydra
->kernel_interface
->bypass_socket(hydra
->kernel_interface
,
403 DBG1(DBG_NET
, "installing IPv4 IKE bypass policy failed");
405 if (!hydra
->kernel_interface
->bypass_socket(hydra
->kernel_interface
,
408 DBG1(DBG_NET
, "installing IPv6 IKE bypass policy failed");
413 METHOD(socket_t
, destroy
, void,
414 private_socket_win_socket_t
*this)
418 for (i
= 0; i
< SOCKET_COUNT
; i
++)
420 if (this->socks
[i
] != INVALID_SOCKET
)
422 closesocket(this->socks
[i
]);
424 if (this->events
[i
] != WSA_INVALID_EVENT
)
426 WSACloseEvent(this->events
[i
]);
433 * See header for description
435 socket_win_socket_t
*socket_win_socket_create()
437 private_socket_win_socket_t
*this;
445 .receive
= _receiver
,
446 .get_port
= _get_port
,
447 .supported_families
= _supported_families
,
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
),
457 .max_packet
= lib
->settings
->get_int(lib
->settings
,
458 "%s.max_packet", PACKET_MAX_DEFAULT
, lib
->ns
),
461 for (i
= 0; i
< SOCKET_COUNT
; i
++)
463 this->socks
[i
] = open_socket(this, i
);
464 this->events
[i
] = WSACreateEvent();
467 for (i
= 0; i
< SOCKET_COUNT
; i
++)
469 if (this->events
[i
] == WSA_INVALID_EVENT
||
470 this->socks
[i
] == INVALID_SOCKET
)
472 DBG1(DBG_NET
, "creating socket failed: %d", WSAGetLastError());
476 if (WSAEventSelect(this->socks
[i
], this->events
[i
],
477 FD_READ
) == SOCKET_ERROR
)
479 DBG1(DBG_NET
, "WSAEventSelect() failed: %d", WSAGetLastError());
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)
492 DBG1(DBG_NET
, "send/recvmsg() lookup failed: %d", WSAGetLastError());
497 return &this->public;