VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 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
RevLine 
[54124]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/*
[98103]7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
[54124]8 *
[96407]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
[54124]26 */
27
[47888]28#include <iprt/asm.h>
29#include <iprt/assert.h>
30#include <iprt/cdefs.h>
[76474]31#include <iprt/errcore.h>
[47888]32
[76474]33#include <iprt/errcore.h>
[47888]34
[62681]35#include <iprt/win/winsock2.h>
[62679]36#include <iprt/win/windows.h>
[47888]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",
[48956]44 domain, type, protocol, socket_vector));
[47888]45 switch (domain)
46 {
47 case AF_INET:
[48956]48 break;
[47888]49 case AF_INET6: /* I dobt we really need it. */
50 default:
[48956]51 AssertMsgFailedReturn(("Unsuported domain:%d\n", domain),
52 VERR_INVALID_PARAMETER);
[47888]53 }
[48956]54
[47888]55 switch(type)
56 {
57 case SOCK_STREAM:
58 case SOCK_DGRAM:
[48956]59 break;
[47888]60 default:
[48956]61 AssertMsgFailedReturn(("Unsuported type:%d\n", type),
62 VERR_INVALID_PARAMETER);
[47888]63 }
[48956]64
[47888]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;
[48956]72
[47888]73 union {
[48956]74 struct sockaddr_in in_addr;
75 struct sockaddr addr;
[47888]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 {
[48956]88 listener = WSASocket(domain, type, protocol, 0, NULL, 0);
[47888]89
[48956]90 if (listener == INVALID_SOCKET)
91 {
92 return VERR_INTERNAL_ERROR;
93 }
[47888]94
[48956]95 int reuse = 1;
96 cb = sizeof(int);
97 int rc = setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, cb);
[47888]98
[48956]99 if (rc)
100 {
101 goto close_socket;
102 }
[47888]103
[48956]104 cb = sizeof(sa[0]);
105 rc = bind(listener, &sa[0].addr, cb);
106 if(rc)
107 {
108 goto close_socket;
109 }
[47888]110
[48956]111 memset(&sa[0], 0, cb);
112 rc = getsockname(listener, &sa[0].addr, &cb);
113 if (rc)
114 {
115 goto close_socket;
116 }
[47888]117
[48956]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);
[47888]142 }
143 else
144 {
[48956]145 socket_vector[0] = WSASocket(domain, type, protocol, 0, NULL, 0);
[47888]146
[48956]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 }
[47888]154
[48956]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;
[47888]158
[48956]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 }
[47888]166
[48956]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);
[47888]173
[48956]174 rc = ioctlsocket(socket_vector[1], FIONBIO, &mode);
175 AssertMsgReturn(rc != SOCKET_ERROR,
176 ("ioctl error: %d\n", WSAGetLastError()),
177 VERR_INTERNAL_ERROR);
178 }
[47888]179
[48956]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 }
[47888]187
[48956]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 }
[47888]194
[48956]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 }
[47888]208 }
[68766]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
[47888]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