VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/RTWinSocketPair.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.1 KB
Line 
1/* $Id: RTWinSocketPair.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * NAT Network - socketpair(2) emulation for winsock.
4 */
5
6/*
7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <iprt/asm.h>
29#include <iprt/assert.h>
30#include <iprt/cdefs.h>
31#include <iprt/errcore.h>
32
33#include <iprt/errcore.h>
34
35#include <iprt/win/winsock2.h>
36#include <iprt/win/windows.h>
37
38#include <stdio.h>
39#include <iprt/log.h>
40
41extern "C" int RTWinSocketPair(int domain, int type, int protocol, SOCKET socket_vector[2])
42{
43 LogFlowFunc(("ENTER: domain:%d, type:%d, protocol:%d, socket_vector:%p\n",
44 domain, type, protocol, socket_vector));
45 switch (domain)
46 {
47 case AF_INET:
48 break;
49 case AF_INET6: /* I dobt we really need it. */
50 default:
51 AssertMsgFailedReturn(("Unsuported domain:%d\n", domain),
52 VERR_INVALID_PARAMETER);
53 }
54
55 switch(type)
56 {
57 case SOCK_STREAM:
58 case SOCK_DGRAM:
59 break;
60 default:
61 AssertMsgFailedReturn(("Unsuported type:%d\n", type),
62 VERR_INVALID_PARAMETER);
63 }
64
65 AssertPtrReturn(socket_vector, VERR_INVALID_PARAMETER);
66 if (!socket_vector)
67 return VERR_INVALID_PARAMETER;
68
69 socket_vector[0] = socket_vector[1] = INVALID_SOCKET;
70
71 SOCKET listener = INVALID_SOCKET;
72
73 union {
74 struct sockaddr_in in_addr;
75 struct sockaddr addr;
76 } sa[2];
77
78 int cb = sizeof(sa);
79 memset(&sa, 0, cb);
80
81 sa[0].in_addr.sin_family = domain;
82 sa[0].in_addr.sin_addr.s_addr = RT_H2N_U32(INADDR_LOOPBACK);
83 sa[0].in_addr.sin_port = 0;
84 cb = sizeof(sa[0]);
85
86 if (type == SOCK_STREAM)
87 {
88 listener = WSASocket(domain, type, protocol, 0, NULL, 0);
89
90 if (listener == INVALID_SOCKET)
91 {
92 return VERR_INTERNAL_ERROR;
93 }
94
95 int reuse = 1;
96 cb = sizeof(int);
97 int rc = setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, cb);
98
99 if (rc)
100 {
101 goto close_socket;
102 }
103
104 cb = sizeof(sa[0]);
105 rc = bind(listener, &sa[0].addr, cb);
106 if(rc)
107 {
108 goto close_socket;
109 }
110
111 memset(&sa[0], 0, cb);
112 rc = getsockname(listener, &sa[0].addr, &cb);
113 if (rc)
114 {
115 goto close_socket;
116 }
117
118 rc = listen(listener, 1);
119 if (rc)
120 {
121 goto close_socket;
122 }
123
124 socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0);
125 if (socket_vector[0] == INVALID_SOCKET)
126 {
127 goto close_socket;
128 }
129
130 rc = connect(socket_vector[0], &sa[0].addr, cb);
131 if (rc)
132 goto close_socket;
133
134
135 socket_vector[1] = accept(listener, NULL, NULL);
136 if (socket_vector[1] == INVALID_SOCKET)
137 {
138 goto close_socket;
139 }
140
141 closesocket(listener);
142 }
143 else
144 {
145 socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0);
146
147 cb = sizeof(sa[0]);
148 int rc = bind(socket_vector[0], &sa[0].addr, cb);
149 Assert(rc != SOCKET_ERROR);
150 if (rc == SOCKET_ERROR)
151 {
152 goto close_socket;
153 }
154
155 sa[1].in_addr.sin_family = domain;
156 sa[1].in_addr.sin_addr.s_addr = RT_H2N_U32(INADDR_LOOPBACK);
157 sa[1].in_addr.sin_port = 0;
158
159 socket_vector[1] = WSASocket(domain, type, protocol, 0, NULL, 0);
160 rc = bind(socket_vector[1], &sa[1].addr, cb);
161 Assert(rc != SOCKET_ERROR);
162 if (rc == SOCKET_ERROR)
163 {
164 goto close_socket;
165 }
166
167 {
168 u_long mode = 0;
169 rc = ioctlsocket(socket_vector[0], FIONBIO, &mode);
170 AssertMsgReturn(rc != SOCKET_ERROR,
171 ("ioctl error: %d\n", WSAGetLastError()),
172 VERR_INTERNAL_ERROR);
173
174 rc = ioctlsocket(socket_vector[1], FIONBIO, &mode);
175 AssertMsgReturn(rc != SOCKET_ERROR,
176 ("ioctl error: %d\n", WSAGetLastError()),
177 VERR_INTERNAL_ERROR);
178 }
179
180 memset(&sa, 0, 2 * cb);
181 rc = getsockname(socket_vector[0], &sa[0].addr, &cb);
182 Assert(rc != SOCKET_ERROR);
183 if (rc == SOCKET_ERROR)
184 {
185 goto close_socket;
186 }
187
188 rc = getsockname(socket_vector[1], &sa[1].addr, &cb);
189 Assert(rc != SOCKET_ERROR);
190 if (rc == SOCKET_ERROR)
191 {
192 goto close_socket;
193 }
194
195 rc = connect(socket_vector[0], &sa[1].addr, cb);
196 Assert(rc != SOCKET_ERROR);
197 if (rc == SOCKET_ERROR)
198 {
199 goto close_socket;
200 }
201
202 rc = connect(socket_vector[1], &sa[0].addr, cb);
203 Assert(rc != SOCKET_ERROR);
204 if (rc == SOCKET_ERROR)
205 {
206 goto close_socket;
207 }
208 }
209
210 for (int i = 0; i < 2; ++i) {
211 SOCKET s = socket_vector[i];
212 u_long mode = 1;
213
214 int status = ioctlsocket(s, FIONBIO, &mode);
215 if (status == SOCKET_ERROR) {
216 LogRel(("FIONBIO: %R[sockerr]\n", WSAGetLastError()));
217 }
218 }
219
220 LogFlowFuncLeaveRC(VINF_SUCCESS);
221 return VINF_SUCCESS;
222
223close_socket:
224 if (listener != INVALID_SOCKET)
225 closesocket(listener);
226
227 if (socket_vector[0] != INVALID_SOCKET)
228 closesocket(socket_vector[0]);
229
230 if (socket_vector[1] != INVALID_SOCKET)
231 closesocket(socket_vector[1]);
232
233 LogFlowFuncLeaveRC(VERR_INTERNAL_ERROR);
234 return VERR_INTERNAL_ERROR;
235}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use