1 | /* SPDX-License-Identifier: MIT */ |
2 | /* |
3 | * util.c (mostly based on QEMU os-win32.c) |
4 | * |
5 | * Copyright (c) 2003-2008 Fabrice Bellard |
6 | * Copyright (c) 2010-2016 Red Hat, Inc. |
7 | * |
8 | * QEMU library functions for win32 which are shared between QEMU and |
9 | * the QEMU tools. |
10 | * |
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
12 | * of this software and associated documentation files (the "Software"), to deal |
13 | * in the Software without restriction, including without limitation the rights |
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
15 | * copies of the Software, and to permit persons to whom the Software is |
16 | * furnished to do so, subject to the following conditions: |
17 | * |
18 | * The above copyright notice and this permission notice shall be included in |
19 | * all copies or substantial portions of the Software. |
20 | * |
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
24 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
27 | * THE SOFTWARE. |
28 | */ |
29 | #include "util.h" |
30 | |
31 | #include <glib.h> |
32 | #include <fcntl.h> |
33 | #include <stdint.h> |
34 | |
35 | #if defined(_WIN32) |
36 | int slirp_inet_aton(const char *cp, struct in_addr *ia) |
37 | { |
38 | uint32_t addr = inet_addr(cp); |
39 | if (addr == 0xffffffff) { |
40 | return 0; |
41 | } |
42 | ia->s_addr = addr; |
43 | return 1; |
44 | } |
45 | #endif |
46 | |
47 | void slirp_set_nonblock(int fd) |
48 | { |
49 | #ifndef _WIN32 |
50 | int f; |
51 | f = fcntl(fd, F_GETFL); |
52 | assert(f != -1); |
53 | f = fcntl(fd, F_SETFL, f | O_NONBLOCK); |
54 | assert(f != -1); |
55 | #else |
56 | unsigned long opt = 1; |
57 | ioctlsocket(fd, FIONBIO, &opt); |
58 | #endif |
59 | } |
60 | |
61 | static void slirp_set_cloexec(int fd) |
62 | { |
63 | #ifndef _WIN32 |
64 | int f; |
65 | f = fcntl(fd, F_GETFD); |
66 | assert(f != -1); |
67 | f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); |
68 | assert(f != -1); |
69 | #endif |
70 | } |
71 | |
72 | /* |
73 | * Opens a socket with FD_CLOEXEC set |
74 | */ |
75 | int slirp_socket(int domain, int type, int protocol) |
76 | { |
77 | int ret; |
78 | |
79 | #ifdef SOCK_CLOEXEC |
80 | ret = socket(domain, type | SOCK_CLOEXEC, protocol); |
81 | if (ret != -1 || errno != EINVAL) { |
82 | return ret; |
83 | } |
84 | #endif |
85 | ret = socket(domain, type, protocol); |
86 | if (ret >= 0) { |
87 | slirp_set_cloexec(ret); |
88 | } |
89 | |
90 | return ret; |
91 | } |
92 | |
93 | #ifdef _WIN32 |
94 | static int socket_error(void) |
95 | { |
96 | switch (WSAGetLastError()) { |
97 | case 0: |
98 | return 0; |
99 | case WSAEINTR: |
100 | return EINTR; |
101 | case WSAEINVAL: |
102 | return EINVAL; |
103 | case WSA_INVALID_HANDLE: |
104 | return EBADF; |
105 | case WSA_NOT_ENOUGH_MEMORY: |
106 | return ENOMEM; |
107 | case WSA_INVALID_PARAMETER: |
108 | return EINVAL; |
109 | case WSAENAMETOOLONG: |
110 | return ENAMETOOLONG; |
111 | case WSAENOTEMPTY: |
112 | return ENOTEMPTY; |
113 | case WSAEWOULDBLOCK: |
114 | /* not using EWOULDBLOCK as we don't want code to have |
115 | * to check both EWOULDBLOCK and EAGAIN */ |
116 | return EAGAIN; |
117 | case WSAEINPROGRESS: |
118 | return EINPROGRESS; |
119 | case WSAEALREADY: |
120 | return EALREADY; |
121 | case WSAENOTSOCK: |
122 | return ENOTSOCK; |
123 | case WSAEDESTADDRREQ: |
124 | return EDESTADDRREQ; |
125 | case WSAEMSGSIZE: |
126 | return EMSGSIZE; |
127 | case WSAEPROTOTYPE: |
128 | return EPROTOTYPE; |
129 | case WSAENOPROTOOPT: |
130 | return ENOPROTOOPT; |
131 | case WSAEPROTONOSUPPORT: |
132 | return EPROTONOSUPPORT; |
133 | case WSAEOPNOTSUPP: |
134 | return EOPNOTSUPP; |
135 | case WSAEAFNOSUPPORT: |
136 | return EAFNOSUPPORT; |
137 | case WSAEADDRINUSE: |
138 | return EADDRINUSE; |
139 | case WSAEADDRNOTAVAIL: |
140 | return EADDRNOTAVAIL; |
141 | case WSAENETDOWN: |
142 | return ENETDOWN; |
143 | case WSAENETUNREACH: |
144 | return ENETUNREACH; |
145 | case WSAENETRESET: |
146 | return ENETRESET; |
147 | case WSAECONNABORTED: |
148 | return ECONNABORTED; |
149 | case WSAECONNRESET: |
150 | return ECONNRESET; |
151 | case WSAENOBUFS: |
152 | return ENOBUFS; |
153 | case WSAEISCONN: |
154 | return EISCONN; |
155 | case WSAENOTCONN: |
156 | return ENOTCONN; |
157 | case WSAETIMEDOUT: |
158 | return ETIMEDOUT; |
159 | case WSAECONNREFUSED: |
160 | return ECONNREFUSED; |
161 | case WSAELOOP: |
162 | return ELOOP; |
163 | case WSAEHOSTUNREACH: |
164 | return EHOSTUNREACH; |
165 | default: |
166 | return EIO; |
167 | } |
168 | } |
169 | |
170 | #undef ioctlsocket |
171 | int slirp_ioctlsocket_wrap(int fd, int req, void *val) |
172 | { |
173 | int ret; |
174 | ret = ioctlsocket(fd, req, val); |
175 | if (ret < 0) { |
176 | errno = socket_error(); |
177 | } |
178 | return ret; |
179 | } |
180 | |
181 | #undef closesocket |
182 | int slirp_closesocket_wrap(int fd) |
183 | { |
184 | int ret; |
185 | ret = closesocket(fd); |
186 | if (ret < 0) { |
187 | errno = socket_error(); |
188 | } |
189 | return ret; |
190 | } |
191 | |
192 | #undef connect |
193 | int slirp_connect_wrap(int sockfd, const struct sockaddr *addr, int addrlen) |
194 | { |
195 | int ret; |
196 | ret = connect(sockfd, addr, addrlen); |
197 | if (ret < 0) { |
198 | errno = socket_error(); |
199 | } |
200 | return ret; |
201 | } |
202 | |
203 | #undef listen |
204 | int slirp_listen_wrap(int sockfd, int backlog) |
205 | { |
206 | int ret; |
207 | ret = listen(sockfd, backlog); |
208 | if (ret < 0) { |
209 | errno = socket_error(); |
210 | } |
211 | return ret; |
212 | } |
213 | |
214 | #undef bind |
215 | int slirp_bind_wrap(int sockfd, const struct sockaddr *addr, int addrlen) |
216 | { |
217 | int ret; |
218 | ret = bind(sockfd, addr, addrlen); |
219 | if (ret < 0) { |
220 | errno = socket_error(); |
221 | } |
222 | return ret; |
223 | } |
224 | |
225 | #undef socket |
226 | int slirp_socket_wrap(int domain, int type, int protocol) |
227 | { |
228 | int ret; |
229 | ret = socket(domain, type, protocol); |
230 | if (ret < 0) { |
231 | errno = socket_error(); |
232 | } |
233 | return ret; |
234 | } |
235 | |
236 | #undef accept |
237 | int slirp_accept_wrap(int sockfd, struct sockaddr *addr, int *addrlen) |
238 | { |
239 | int ret; |
240 | ret = accept(sockfd, addr, addrlen); |
241 | if (ret < 0) { |
242 | errno = socket_error(); |
243 | } |
244 | return ret; |
245 | } |
246 | |
247 | #undef shutdown |
248 | int slirp_shutdown_wrap(int sockfd, int how) |
249 | { |
250 | int ret; |
251 | ret = shutdown(sockfd, how); |
252 | if (ret < 0) { |
253 | errno = socket_error(); |
254 | } |
255 | return ret; |
256 | } |
257 | |
258 | #undef getsockopt |
259 | int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, |
260 | int *optlen) |
261 | { |
262 | int ret; |
263 | ret = getsockopt(sockfd, level, optname, optval, optlen); |
264 | if (ret < 0) { |
265 | errno = socket_error(); |
266 | } |
267 | return ret; |
268 | } |
269 | |
270 | #undef setsockopt |
271 | int slirp_setsockopt_wrap(int sockfd, int level, int optname, |
272 | const void *optval, int optlen) |
273 | { |
274 | int ret; |
275 | ret = setsockopt(sockfd, level, optname, optval, optlen); |
276 | if (ret < 0) { |
277 | errno = socket_error(); |
278 | } |
279 | return ret; |
280 | } |
281 | |
282 | #undef getpeername |
283 | int slirp_getpeername_wrap(int sockfd, struct sockaddr *addr, int *addrlen) |
284 | { |
285 | int ret; |
286 | ret = getpeername(sockfd, addr, addrlen); |
287 | if (ret < 0) { |
288 | errno = socket_error(); |
289 | } |
290 | return ret; |
291 | } |
292 | |
293 | #undef getsockname |
294 | int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr, int *addrlen) |
295 | { |
296 | int ret; |
297 | ret = getsockname(sockfd, addr, addrlen); |
298 | if (ret < 0) { |
299 | errno = socket_error(); |
300 | } |
301 | return ret; |
302 | } |
303 | |
304 | #undef send |
305 | ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags) |
306 | { |
307 | int ret; |
308 | ret = send(sockfd, buf, len, flags); |
309 | if (ret < 0) { |
310 | errno = socket_error(); |
311 | } |
312 | return ret; |
313 | } |
314 | |
315 | #undef sendto |
316 | ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags, |
317 | const struct sockaddr *addr, int addrlen) |
318 | { |
319 | int ret; |
320 | ret = sendto(sockfd, buf, len, flags, addr, addrlen); |
321 | if (ret < 0) { |
322 | errno = socket_error(); |
323 | } |
324 | return ret; |
325 | } |
326 | |
327 | #undef recv |
328 | ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags) |
329 | { |
330 | int ret; |
331 | ret = recv(sockfd, buf, len, flags); |
332 | if (ret < 0) { |
333 | errno = socket_error(); |
334 | } |
335 | return ret; |
336 | } |
337 | |
338 | #undef recvfrom |
339 | ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, |
340 | struct sockaddr *addr, int *addrlen) |
341 | { |
342 | int ret; |
343 | ret = recvfrom(sockfd, buf, len, flags, addr, addrlen); |
344 | if (ret < 0) { |
345 | errno = socket_error(); |
346 | } |
347 | return ret; |
348 | } |
349 | #endif /* WIN32 */ |
350 | |
351 | void slirp_pstrcpy(char *buf, int buf_size, const char *str) |
352 | { |
353 | int c; |
354 | char *q = buf; |
355 | |
356 | if (buf_size <= 0) |
357 | return; |
358 | |
359 | for (;;) { |
360 | c = *str++; |
361 | if (c == 0 || q >= buf + buf_size - 1) |
362 | break; |
363 | *q++ = c; |
364 | } |
365 | *q = '\0'; |
366 | } |
367 | |