]>
Commit | Line | Data |
---|---|---|
6087fd53 | 1 | /* SPDX-License-Identifier: MIT */ |
707bd47e MAL |
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 | ||
5a4af0d4 MAL |
35 | #if defined(_WIN32) |
36 | int slirp_inet_aton(const char *cp, struct in_addr *ia) | |
707bd47e MAL |
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 | ||
848c7092 MAL |
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 | ||
707bd47e MAL |
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 | |
adf1add2 | 171 | int slirp_ioctlsocket_wrap(int fd, int req, void *val) |
707bd47e MAL |
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 | |
adf1add2 | 182 | int slirp_closesocket_wrap(int fd) |
707bd47e MAL |
183 | { |
184 | int ret; | |
185 | ret = closesocket(fd); | |
186 | if (ret < 0) { | |
187 | errno = socket_error(); | |
188 | } | |
189 | return ret; | |
190 | } | |
adf1add2 MAL |
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, | |
260 | void *optval, 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, | |
284 | int *addrlen) | |
285 | { | |
286 | int ret; | |
287 | ret = getpeername(sockfd, addr, addrlen); | |
288 | if (ret < 0) { | |
289 | errno = socket_error(); | |
290 | } | |
291 | return ret; | |
292 | } | |
293 | ||
294 | #undef getsockname | |
295 | int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr, | |
296 | int *addrlen) | |
297 | { | |
298 | int ret; | |
299 | ret = getsockname(sockfd, addr, addrlen); | |
300 | if (ret < 0) { | |
301 | errno = socket_error(); | |
302 | } | |
303 | return ret; | |
304 | } | |
305 | ||
306 | #undef send | |
307 | ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags) | |
308 | { | |
309 | int ret; | |
310 | ret = send(sockfd, buf, len, flags); | |
311 | if (ret < 0) { | |
312 | errno = socket_error(); | |
313 | } | |
314 | return ret; | |
315 | } | |
316 | ||
317 | #undef sendto | |
318 | ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags, | |
319 | const struct sockaddr *addr, int addrlen) | |
320 | { | |
321 | int ret; | |
322 | ret = sendto(sockfd, buf, len, flags, addr, addrlen); | |
323 | if (ret < 0) { | |
324 | errno = socket_error(); | |
325 | } | |
326 | return ret; | |
327 | } | |
328 | ||
329 | #undef recv | |
330 | ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags) | |
331 | { | |
332 | int ret; | |
333 | ret = recv(sockfd, buf, len, flags); | |
334 | if (ret < 0) { | |
335 | errno = socket_error(); | |
336 | } | |
337 | return ret; | |
338 | } | |
339 | ||
340 | #undef recvfrom | |
341 | ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, | |
342 | struct sockaddr *addr, int *addrlen) | |
343 | { | |
344 | int ret; | |
345 | ret = recvfrom(sockfd, buf, len, flags, addr, addrlen); | |
346 | if (ret < 0) { | |
347 | errno = socket_error(); | |
348 | } | |
349 | return ret; | |
350 | } | |
707bd47e | 351 | #endif /* WIN32 */ |
d1c4b3e9 MAL |
352 | |
353 | void slirp_pstrcpy(char *buf, int buf_size, const char *str) | |
354 | { | |
355 | int c; | |
356 | char *q = buf; | |
357 | ||
358 | if (buf_size <= 0) | |
359 | return; | |
360 | ||
361 | for(;;) { | |
362 | c = *str++; | |
363 | if (c == 0 || q >= buf + buf_size - 1) | |
364 | break; | |
365 | *q++ = c; | |
366 | } | |
367 | *q = '\0'; | |
368 | } |