[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 |
|
---|
| 41 | extern "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 |
|
---|
| 223 | close_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 | }
|
---|