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