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