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)
slirp_inet_aton(const char * cp,struct in_addr * ia)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
slirp_set_nonblock(int fd)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
slirp_set_cloexec(int fd)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 */
slirp_socket(int domain,int type,int protocol)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
socket_error(void)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
slirp_ioctlsocket_wrap(int fd,int req,void * val)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
slirp_closesocket_wrap(int fd)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
slirp_connect_wrap(int sockfd,const struct sockaddr * addr,int addrlen)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
slirp_listen_wrap(int sockfd,int backlog)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
slirp_bind_wrap(int sockfd,const struct sockaddr * addr,int addrlen)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
slirp_socket_wrap(int domain,int type,int protocol)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
slirp_accept_wrap(int sockfd,struct sockaddr * addr,int * addrlen)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
slirp_shutdown_wrap(int sockfd,int how)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
slirp_getsockopt_wrap(int sockfd,int level,int optname,void * optval,int * optlen)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
slirp_setsockopt_wrap(int sockfd,int level,int optname,const void * optval,int optlen)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
slirp_getpeername_wrap(int sockfd,struct sockaddr * addr,int * addrlen)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
slirp_getsockname_wrap(int sockfd,struct sockaddr * addr,int * addrlen)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
slirp_send_wrap(int sockfd,const void * buf,size_t len,int flags)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
slirp_sendto_wrap(int sockfd,const void * buf,size_t len,int flags,const struct sockaddr * addr,int addrlen)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
slirp_recv_wrap(int sockfd,void * buf,size_t len,int flags)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
slirp_recvfrom_wrap(int sockfd,void * buf,size_t len,int flags,struct sockaddr * addr,int * addrlen)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
slirp_pstrcpy(char * buf,int buf_size,const char * str)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
slirp_vsnprintf(char * str,size_t size,const char * format,va_list args)368 static int slirp_vsnprintf(char *str, size_t size,
369 const char *format, va_list args)
370 {
371 int rv = g_vsnprintf(str, size, format, args);
372
373 if (rv < 0) {
374 g_error("g_vsnprintf() failed: %s", g_strerror(errno));
375 }
376
377 return rv;
378 }
379
380 /*
381 * A snprintf()-like function that:
382 * - returns the number of bytes written (excluding optional \0-ending)
383 * - dies on error
384 * - warn on truncation
385 */
slirp_fmt(char * str,size_t size,const char * format,...)386 int slirp_fmt(char *str, size_t size, const char *format, ...)
387 {
388 va_list args;
389 int rv;
390
391 va_start(args, format);
392 rv = slirp_vsnprintf(str, size, format, args);
393 va_end(args);
394
395 if (rv > size) {
396 g_critical("slirp_fmt() truncation");
397 }
398
399 return MIN(rv, size);
400 }
401
402 /*
403 * A snprintf()-like function that:
404 * - always \0-end (unless size == 0)
405 * - returns the number of bytes actually written, including \0 ending
406 * - dies on error
407 * - warn on truncation
408 */
slirp_fmt0(char * str,size_t size,const char * format,...)409 int slirp_fmt0(char *str, size_t size, const char *format, ...)
410 {
411 va_list args;
412 int rv;
413
414 va_start(args, format);
415 rv = slirp_vsnprintf(str, size, format, args);
416 va_end(args);
417
418 if (rv >= size) {
419 g_critical("slirp_fmt0() truncation");
420 if (size > 0)
421 str[size - 1] = '\0';
422 rv = size;
423 } else {
424 rv += 1; /* include \0 */
425 }
426
427 return rv;
428 }
429