qemu/slirp/src/util.c
<<
>>
Prefs
   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)
  36int 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
  47void 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
  61static 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 */
  75int 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
  94static 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
 171int 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
 182int 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
 193int 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
 204int 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
 215int 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
 226int 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
 237int 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
 248int 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
 259int 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
 271int 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
 283int 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
 295int 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
 307ssize_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
 318ssize_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
 330ssize_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
 341ssize_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}
 351#endif /* WIN32 */
 352
 353void 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}
 369