Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/util.c
2 views
/* SPDX-License-Identifier: MIT */1/*2* util.c (mostly based on QEMU os-win32.c)3*4* Copyright (c) 2003-2008 Fabrice Bellard5* Copyright (c) 2010-2016 Red Hat, Inc.6*7* QEMU library functions for win32 which are shared between QEMU and8* the QEMU tools.9*10* Permission is hereby granted, free of charge, to any person obtaining a copy11* of this software and associated documentation files (the "Software"), to deal12* in the Software without restriction, including without limitation the rights13* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell14* copies of the Software, and to permit persons to whom the Software is15* furnished to do so, subject to the following conditions:16*17* The above copyright notice and this permission notice shall be included in18* all copies or substantial portions of the Software.19*20* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR21* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,22* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL23* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER24* 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 IN26* THE SOFTWARE.27*/28#include "util.h"2930#include <glib.h>31#include <fcntl.h>32#include <stdint.h>3334#if defined(_WIN32)35int slirp_inet_aton(const char *cp, struct in_addr *ia)36{37uint32_t addr = inet_addr(cp);38if (addr == 0xffffffff) {39return 0;40}41ia->s_addr = addr;42return 1;43}44#endif4546void slirp_set_nonblock(int fd)47{48#ifndef _WIN3249int f;50f = fcntl(fd, F_GETFL);51assert(f != -1);52f = fcntl(fd, F_SETFL, f | O_NONBLOCK);53assert(f != -1);54#else55unsigned long opt = 1;56ioctlsocket(fd, FIONBIO, &opt);57#endif58}5960static void slirp_set_cloexec(int fd)61{62#ifndef _WIN3263int f;64f = fcntl(fd, F_GETFD);65assert(f != -1);66f = fcntl(fd, F_SETFD, f | FD_CLOEXEC);67assert(f != -1);68#endif69}7071/*72* Opens a socket with FD_CLOEXEC set73* On failure errno contains the reason.74*/75int slirp_socket(int domain, int type, int protocol)76{77int ret;7879#ifdef SOCK_CLOEXEC80ret = socket(domain, type | SOCK_CLOEXEC, protocol);81if (ret != -1 || errno != EINVAL) {82return ret;83}84#endif85ret = socket(domain, type, protocol);86if (ret >= 0) {87slirp_set_cloexec(ret);88}8990return ret;91}9293#ifdef _WIN3294static int socket_error(void)95{96switch (WSAGetLastError()) {97case 0:98return 0;99case WSAEINTR:100return EINTR;101case WSAEINVAL:102return EINVAL;103case WSA_INVALID_HANDLE:104return EBADF;105case WSA_NOT_ENOUGH_MEMORY:106return ENOMEM;107case WSA_INVALID_PARAMETER:108return EINVAL;109case WSAENAMETOOLONG:110return ENAMETOOLONG;111case WSAENOTEMPTY:112return ENOTEMPTY;113case WSAEWOULDBLOCK:114/* not using EWOULDBLOCK as we don't want code to have115* to check both EWOULDBLOCK and EAGAIN */116return EAGAIN;117case WSAEINPROGRESS:118return EINPROGRESS;119case WSAEALREADY:120return EALREADY;121case WSAENOTSOCK:122return ENOTSOCK;123case WSAEDESTADDRREQ:124return EDESTADDRREQ;125case WSAEMSGSIZE:126return EMSGSIZE;127case WSAEPROTOTYPE:128return EPROTOTYPE;129case WSAENOPROTOOPT:130return ENOPROTOOPT;131case WSAEPROTONOSUPPORT:132return EPROTONOSUPPORT;133case WSAEOPNOTSUPP:134return EOPNOTSUPP;135case WSAEAFNOSUPPORT:136return EAFNOSUPPORT;137case WSAEADDRINUSE:138return EADDRINUSE;139case WSAEADDRNOTAVAIL:140return EADDRNOTAVAIL;141case WSAENETDOWN:142return ENETDOWN;143case WSAENETUNREACH:144return ENETUNREACH;145case WSAENETRESET:146return ENETRESET;147case WSAECONNABORTED:148return ECONNABORTED;149case WSAECONNRESET:150return ECONNRESET;151case WSAENOBUFS:152return ENOBUFS;153case WSAEISCONN:154return EISCONN;155case WSAENOTCONN:156return ENOTCONN;157case WSAETIMEDOUT:158return ETIMEDOUT;159case WSAECONNREFUSED:160return ECONNREFUSED;161case WSAELOOP:162return ELOOP;163case WSAEHOSTUNREACH:164return EHOSTUNREACH;165default:166return EIO;167}168}169170#undef ioctlsocket171int slirp_ioctlsocket_wrap(int fd, int req, void *val)172{173int ret;174ret = ioctlsocket(fd, req, val);175if (ret < 0) {176errno = socket_error();177}178return ret;179}180181#undef closesocket182int slirp_closesocket_wrap(int fd)183{184int ret;185ret = closesocket(fd);186if (ret < 0) {187errno = socket_error();188}189return ret;190}191192#undef connect193int slirp_connect_wrap(int sockfd, const struct sockaddr *addr, int addrlen)194{195int ret;196ret = connect(sockfd, addr, addrlen);197if (ret < 0) {198errno = socket_error();199}200return ret;201}202203#undef listen204int slirp_listen_wrap(int sockfd, int backlog)205{206int ret;207ret = listen(sockfd, backlog);208if (ret < 0) {209errno = socket_error();210}211return ret;212}213214#undef bind215int slirp_bind_wrap(int sockfd, const struct sockaddr *addr, int addrlen)216{217int ret;218ret = bind(sockfd, addr, addrlen);219if (ret < 0) {220errno = socket_error();221}222return ret;223}224225#undef socket226int slirp_socket_wrap(int domain, int type, int protocol)227{228int ret;229ret = socket(domain, type, protocol);230if (ret < 0) {231errno = socket_error();232}233return ret;234}235236#undef accept237int slirp_accept_wrap(int sockfd, struct sockaddr *addr, int *addrlen)238{239int ret;240ret = accept(sockfd, addr, addrlen);241if (ret < 0) {242errno = socket_error();243}244return ret;245}246247#undef shutdown248int slirp_shutdown_wrap(int sockfd, int how)249{250int ret;251ret = shutdown(sockfd, how);252if (ret < 0) {253errno = socket_error();254}255return ret;256}257258#undef getsockopt259int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval,260int *optlen)261{262int ret;263ret = getsockopt(sockfd, level, optname, optval, optlen);264if (ret < 0) {265errno = socket_error();266}267return ret;268}269270#undef setsockopt271int slirp_setsockopt_wrap(int sockfd, int level, int optname,272const void *optval, int optlen)273{274int ret;275ret = setsockopt(sockfd, level, optname, optval, optlen);276if (ret < 0) {277errno = socket_error();278}279return ret;280}281282#undef getpeername283int slirp_getpeername_wrap(int sockfd, struct sockaddr *addr, int *addrlen)284{285int ret;286ret = getpeername(sockfd, addr, addrlen);287if (ret < 0) {288errno = socket_error();289}290return ret;291}292293#undef getsockname294int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr, int *addrlen)295{296int ret;297ret = getsockname(sockfd, addr, addrlen);298if (ret < 0) {299errno = socket_error();300}301return ret;302}303304#undef send305slirp_ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags)306{307int ret;308ret = send(sockfd, buf, len, flags);309if (ret < 0) {310errno = socket_error();311}312return ret;313}314315#undef sendto316slirp_ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,317const struct sockaddr *addr, int addrlen)318{319int ret;320ret = sendto(sockfd, buf, len, flags, addr, addrlen);321if (ret < 0) {322errno = socket_error();323}324return ret;325}326327#undef recv328slirp_ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags)329{330int ret;331ret = recv(sockfd, buf, len, flags);332if (ret < 0) {333errno = socket_error();334}335return ret;336}337338#undef recvfrom339slirp_ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,340struct sockaddr *addr, int *addrlen)341{342int ret;343ret = recvfrom(sockfd, buf, len, flags, addr, addrlen);344if (ret < 0) {345errno = socket_error();346}347return ret;348}349#endif /* WIN32 */350351void slirp_pstrcpy(char *buf, int buf_size, const char *str)352{353int c;354char *q = buf;355356if (buf_size <= 0)357return;358359for (;;) {360c = *str++;361if (c == 0 || q >= buf + buf_size - 1)362break;363*q++ = c;364}365*q = '\0';366}367368G_GNUC_PRINTF(3, 0)369static int slirp_vsnprintf(char *str, size_t size,370const char *format, va_list args)371{372int rv = g_vsnprintf(str, size, format, args);373374if (rv < 0) {375g_error("g_vsnprintf() failed: %s", g_strerror(errno))376}377378return rv;379}380381/*382* A snprintf()-like function that:383* - returns the number of bytes written (excluding optional \0-ending)384* - dies on error385* - warn on truncation386*/387int slirp_fmt(char *str, size_t size, const char *format, ...)388{389va_list args;390int rv;391392va_start(args, format);393rv = slirp_vsnprintf(str, size, format, args);394va_end(args);395396if (rv >= size) {397printf("[" "hi" ": error] " "hi", "ok");398g_critical("slirp_fmt() truncation", "");399}400401return MIN(rv, size);402}403404/*405* A snprintf()-like function that:406* - always \0-end (unless size == 0)407* - returns the number of bytes actually written, including \0 ending408* - dies on error409* - warn on truncation410*/411int slirp_fmt0(char *str, size_t size, const char *format, ...)412{413va_list args;414int rv;415416va_start(args, format);417rv = slirp_vsnprintf(str, size, format, args);418va_end(args);419420if (rv >= size) {421g_critical("slirp_fmt0() truncation");422if (size > 0)423str[size - 1] = '\0';424rv = size;425} else {426rv += 1; /* include \0 */427}428429return rv;430}431432const char *slirp_ether_ntoa(const uint8_t *addr, char *out_str,433size_t out_str_size)434{435assert(out_str_size >= ETH_ADDRSTRLEN);436437slirp_fmt0(out_str, out_str_size, "%02x:%02x:%02x:%02x:%02x:%02x",438addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);439440return out_str;441}442443444