qemu/slirp/src/slirp.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: MIT */
   2/*
   3 * libslirp glue
   4 *
   5 * Copyright (c) 2004-2008 Fabrice Bellard
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#include "slirp.h"
  26
  27
  28#ifndef _WIN32
  29#include <net/if.h>
  30#endif
  31
  32int slirp_debug;
  33
  34/* Define to 1 if you want KEEPALIVE timers */
  35bool slirp_do_keepalive;
  36
  37/* host loopback address */
  38struct in_addr loopback_addr;
  39/* host loopback network mask */
  40unsigned long loopback_mask;
  41
  42/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
  43static const uint8_t special_ethaddr[ETH_ALEN] = {
  44    0x52, 0x55, 0x00, 0x00, 0x00, 0x00
  45};
  46
  47unsigned curtime;
  48
  49static struct in_addr dns_addr;
  50#ifndef _WIN32
  51static struct in6_addr dns6_addr;
  52#endif
  53static unsigned dns_addr_time;
  54#ifndef _WIN32
  55static unsigned dns6_addr_time;
  56#endif
  57
  58#define TIMEOUT_FAST 2  /* milliseconds */
  59#define TIMEOUT_SLOW 499  /* milliseconds */
  60/* for the aging of certain requests like DNS */
  61#define TIMEOUT_DEFAULT 1000  /* milliseconds */
  62
  63#ifdef _WIN32
  64
  65int get_dns_addr(struct in_addr *pdns_addr)
  66{
  67    FIXED_INFO *FixedInfo=NULL;
  68    ULONG    BufLen;
  69    DWORD    ret;
  70    IP_ADDR_STRING *pIPAddr;
  71    struct in_addr tmp_addr;
  72
  73    if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < TIMEOUT_DEFAULT) {
  74        *pdns_addr = dns_addr;
  75        return 0;
  76    }
  77
  78    FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
  79    BufLen = sizeof(FIXED_INFO);
  80
  81    if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
  82        if (FixedInfo) {
  83            GlobalFree(FixedInfo);
  84            FixedInfo = NULL;
  85        }
  86        FixedInfo = GlobalAlloc(GPTR, BufLen);
  87    }
  88
  89    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
  90        printf("GetNetworkParams failed. ret = %08x\n", (unsigned)ret );
  91        if (FixedInfo) {
  92            GlobalFree(FixedInfo);
  93            FixedInfo = NULL;
  94        }
  95        return -1;
  96    }
  97
  98    pIPAddr = &(FixedInfo->DnsServerList);
  99    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
 100    *pdns_addr = tmp_addr;
 101    dns_addr = tmp_addr;
 102    dns_addr_time = curtime;
 103    if (FixedInfo) {
 104        GlobalFree(FixedInfo);
 105        FixedInfo = NULL;
 106    }
 107    return 0;
 108}
 109
 110int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
 111{
 112    return -1;
 113}
 114
 115static void winsock_cleanup(void)
 116{
 117    WSACleanup();
 118}
 119
 120#else
 121
 122static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
 123                               socklen_t addrlen,
 124                               struct stat *cached_stat, unsigned *cached_time)
 125{
 126    struct stat old_stat;
 127    if (curtime - *cached_time < TIMEOUT_DEFAULT) {
 128        memcpy(pdns_addr, cached_addr, addrlen);
 129        return 0;
 130    }
 131    old_stat = *cached_stat;
 132    if (stat("/etc/resolv.conf", cached_stat) != 0) {
 133        return -1;
 134    }
 135    if (cached_stat->st_dev == old_stat.st_dev
 136        && cached_stat->st_ino == old_stat.st_ino
 137        && cached_stat->st_size == old_stat.st_size
 138        && cached_stat->st_mtime == old_stat.st_mtime) {
 139        memcpy(pdns_addr, cached_addr, addrlen);
 140        return 0;
 141    }
 142    return 1;
 143}
 144
 145static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
 146                                    socklen_t addrlen, uint32_t *scope_id,
 147                                    unsigned *cached_time)
 148{
 149    char buff[512];
 150    char buff2[257];
 151    FILE *f;
 152    int found = 0;
 153    void *tmp_addr = alloca(addrlen);
 154    unsigned if_index;
 155
 156    f = fopen("/etc/resolv.conf", "r");
 157    if (!f)
 158        return -1;
 159
 160    DEBUG_MISC("IP address of your DNS(s):");
 161    while (fgets(buff, 512, f) != NULL) {
 162        if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
 163            char *c = strchr(buff2, '%');
 164            if (c) {
 165                if_index = if_nametoindex(c + 1);
 166                *c = '\0';
 167            } else {
 168                if_index = 0;
 169            }
 170
 171            if (!inet_pton(af, buff2, tmp_addr)) {
 172                continue;
 173            }
 174            /* If it's the first one, set it to dns_addr */
 175            if (!found) {
 176                memcpy(pdns_addr, tmp_addr, addrlen);
 177                memcpy(cached_addr, tmp_addr, addrlen);
 178                if (scope_id) {
 179                    *scope_id = if_index;
 180                }
 181                *cached_time = curtime;
 182            }
 183
 184            if (++found > 3) {
 185                DEBUG_MISC("  (more)");
 186                break;
 187            } else if (slirp_debug & DBG_MISC) {
 188                char s[INET6_ADDRSTRLEN];
 189                const char *res = inet_ntop(af, tmp_addr, s, sizeof(s));
 190                if (!res) {
 191                    res = "  (string conversion error)";
 192                }
 193                DEBUG_MISC("  %s", res);
 194            }
 195        }
 196    }
 197    fclose(f);
 198    if (!found)
 199        return -1;
 200    return 0;
 201}
 202
 203int get_dns_addr(struct in_addr *pdns_addr)
 204{
 205    static struct stat dns_addr_stat;
 206
 207    if (dns_addr.s_addr != 0) {
 208        int ret;
 209        ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
 210                                  &dns_addr_stat, &dns_addr_time);
 211        if (ret <= 0) {
 212            return ret;
 213        }
 214    }
 215    return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr,
 216                                    sizeof(dns_addr), NULL, &dns_addr_time);
 217}
 218
 219int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
 220{
 221    static struct stat dns6_addr_stat;
 222
 223    if (!in6_zero(&dns6_addr)) {
 224        int ret;
 225        ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr),
 226                                  &dns6_addr_stat, &dns6_addr_time);
 227        if (ret <= 0) {
 228            return ret;
 229        }
 230    }
 231    return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr,
 232                                    sizeof(dns6_addr),
 233                                    scope_id, &dns6_addr_time);
 234}
 235
 236#endif
 237
 238static void slirp_init_once(void)
 239{
 240    static int initialized;
 241    const char *debug;
 242#ifdef _WIN32
 243    WSADATA Data;
 244#endif
 245
 246    if (initialized) {
 247        return;
 248    }
 249    initialized = 1;
 250
 251#ifdef _WIN32
 252    WSAStartup(MAKEWORD(2,0), &Data);
 253    atexit(winsock_cleanup);
 254#endif
 255
 256    loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
 257    loopback_mask = htonl(IN_CLASSA_NET);
 258
 259    debug = g_getenv("SLIRP_DEBUG");
 260    if (debug) {
 261        const GDebugKey keys[] = {
 262            { "call", DBG_CALL },
 263            { "misc", DBG_MISC },
 264            { "error", DBG_ERROR },
 265            { "tftp", DBG_TFTP },
 266        };
 267        slirp_debug = g_parse_debug_string(debug, keys, G_N_ELEMENTS(keys));
 268    }
 269
 270
 271}
 272
 273Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
 274                  struct in_addr vnetmask, struct in_addr vhost,
 275                  bool in6_enabled,
 276                  struct in6_addr vprefix_addr6, uint8_t vprefix_len,
 277                  struct in6_addr vhost6, const char *vhostname,
 278                  const char *tftp_server_name,
 279                  const char *tftp_path, const char *bootfile,
 280                  struct in_addr vdhcp_start, struct in_addr vnameserver,
 281                  struct in6_addr vnameserver6, const char **vdnssearch,
 282                  const char *vdomainname,
 283                  const SlirpCb *callbacks,
 284                  void *opaque)
 285{
 286    Slirp *slirp = g_malloc0(sizeof(Slirp));
 287
 288    slirp_init_once();
 289
 290    slirp->opaque = opaque;
 291    slirp->cb = callbacks;
 292    slirp->grand = g_rand_new();
 293    slirp->restricted = restricted;
 294
 295    slirp->in_enabled = in_enabled;
 296    slirp->in6_enabled = in6_enabled;
 297
 298    if_init(slirp);
 299    ip_init(slirp);
 300    ip6_init(slirp);
 301
 302    /* Initialise mbufs *after* setting the MTU */
 303    m_init(slirp);
 304
 305    slirp->vnetwork_addr = vnetwork;
 306    slirp->vnetwork_mask = vnetmask;
 307    slirp->vhost_addr = vhost;
 308    slirp->vprefix_addr6 = vprefix_addr6;
 309    slirp->vprefix_len = vprefix_len;
 310    slirp->vhost_addr6 = vhost6;
 311    if (vhostname) {
 312        slirp_pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
 313                      vhostname);
 314    }
 315    slirp->tftp_prefix = g_strdup(tftp_path);
 316    slirp->bootp_filename = g_strdup(bootfile);
 317    slirp->vdomainname = g_strdup(vdomainname);
 318    slirp->vdhcp_startaddr = vdhcp_start;
 319    slirp->vnameserver_addr = vnameserver;
 320    slirp->vnameserver_addr6 = vnameserver6;
 321    slirp->tftp_server_name = g_strdup(tftp_server_name);
 322
 323    if (vdnssearch) {
 324        translate_dnssearch(slirp, vdnssearch);
 325    }
 326
 327    return slirp;
 328}
 329
 330void slirp_cleanup(Slirp *slirp)
 331{
 332    struct gfwd_list *e, *next;
 333
 334    for (e = slirp->guestfwd_list; e; e = next) {
 335        next = e->ex_next;
 336        g_free(e->ex_exec);
 337        g_free(e);
 338    }
 339
 340    ip_cleanup(slirp);
 341    ip6_cleanup(slirp);
 342    m_cleanup(slirp);
 343
 344    g_rand_free(slirp->grand);
 345
 346    g_free(slirp->vdnssearch);
 347    g_free(slirp->tftp_prefix);
 348    g_free(slirp->bootp_filename);
 349    g_free(slirp->vdomainname);
 350    g_free(slirp);
 351}
 352
 353#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
 354#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
 355
 356static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout)
 357{
 358    uint32_t t;
 359
 360    if (*timeout <= TIMEOUT_FAST) {
 361        return;
 362    }
 363
 364    t = MIN(1000, *timeout);
 365
 366    /* If we have tcp timeout with slirp, then we will fill @timeout with
 367     * more precise value.
 368     */
 369    if (slirp->time_fasttimo) {
 370        *timeout = TIMEOUT_FAST;
 371        return;
 372    }
 373    if (slirp->do_slowtimo) {
 374        t = MIN(TIMEOUT_SLOW, t);
 375    }
 376    *timeout = t;
 377}
 378
 379void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
 380                        SlirpAddPollCb add_poll, void *opaque)
 381{
 382    struct socket *so, *so_next;
 383
 384    /*
 385     * First, TCP sockets
 386     */
 387
 388    /*
 389     * *_slowtimo needs calling if there are IP fragments
 390     * in the fragment queue, or there are TCP connections active
 391     */
 392    slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
 393                          (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
 394
 395    for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) {
 396        int events = 0;
 397
 398        so_next = so->so_next;
 399
 400        so->pollfds_idx = -1;
 401
 402        /*
 403         * See if we need a tcp_fasttimo
 404         */
 405        if (slirp->time_fasttimo == 0 &&
 406            so->so_tcpcb->t_flags & TF_DELACK) {
 407            slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
 408        }
 409
 410        /*
 411         * NOFDREF can include still connecting to local-host,
 412         * newly socreated() sockets etc. Don't want to select these.
 413         */
 414        if (so->so_state & SS_NOFDREF || so->s == -1) {
 415            continue;
 416        }
 417
 418        /*
 419         * Set for reading sockets which are accepting
 420         */
 421        if (so->so_state & SS_FACCEPTCONN) {
 422            so->pollfds_idx = add_poll(so->s,
 423                SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
 424            continue;
 425        }
 426
 427        /*
 428         * Set for writing sockets which are connecting
 429         */
 430        if (so->so_state & SS_ISFCONNECTING) {
 431            so->pollfds_idx = add_poll(so->s,
 432                SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque);
 433            continue;
 434        }
 435
 436        /*
 437         * Set for writing if we are connected, can send more, and
 438         * we have something to send
 439         */
 440        if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
 441            events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR;
 442        }
 443
 444        /*
 445         * Set for reading (and urgent data) if we are connected, can
 446         * receive more, and we have room for it XXX /2 ?
 447         */
 448        if (CONN_CANFRCV(so) &&
 449            (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
 450            events |= SLIRP_POLL_IN | SLIRP_POLL_HUP |
 451                      SLIRP_POLL_ERR | SLIRP_POLL_PRI;
 452        }
 453
 454        if (events) {
 455            so->pollfds_idx = add_poll(so->s, events, opaque);
 456        }
 457    }
 458
 459    /*
 460     * UDP sockets
 461     */
 462    for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
 463        so_next = so->so_next;
 464
 465        so->pollfds_idx = -1;
 466
 467        /*
 468         * See if it's timed out
 469         */
 470        if (so->so_expire) {
 471            if (so->so_expire <= curtime) {
 472                udp_detach(so);
 473                continue;
 474            } else {
 475                slirp->do_slowtimo = true; /* Let socket expire */
 476            }
 477        }
 478
 479        /*
 480         * When UDP packets are received from over the
 481         * link, they're sendto()'d straight away, so
 482         * no need for setting for writing
 483         * Limit the number of packets queued by this session
 484         * to 4.  Note that even though we try and limit this
 485         * to 4 packets, the session could have more queued
 486         * if the packets needed to be fragmented
 487         * (XXX <= 4 ?)
 488         */
 489        if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
 490            so->pollfds_idx = add_poll(so->s,
 491                SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
 492        }
 493    }
 494
 495    /*
 496     * ICMP sockets
 497     */
 498    for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
 499        so_next = so->so_next;
 500
 501        so->pollfds_idx = -1;
 502
 503        /*
 504         * See if it's timed out
 505         */
 506        if (so->so_expire) {
 507            if (so->so_expire <= curtime) {
 508                icmp_detach(so);
 509                continue;
 510            } else {
 511                slirp->do_slowtimo = true; /* Let socket expire */
 512            }
 513        }
 514
 515        if (so->so_state & SS_ISFCONNECTED) {
 516            so->pollfds_idx = add_poll(so->s,
 517                SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
 518        }
 519    }
 520
 521    slirp_update_timeout(slirp, timeout);
 522}
 523
 524void slirp_pollfds_poll(Slirp *slirp, int select_error,
 525                        SlirpGetREventsCb get_revents, void *opaque)
 526{
 527    struct socket *so, *so_next;
 528    int ret;
 529
 530    curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS;
 531
 532    /*
 533     * See if anything has timed out
 534     */
 535    if (slirp->time_fasttimo &&
 536        ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) {
 537        tcp_fasttimo(slirp);
 538        slirp->time_fasttimo = 0;
 539    }
 540    if (slirp->do_slowtimo &&
 541        ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) {
 542        ip_slowtimo(slirp);
 543        tcp_slowtimo(slirp);
 544        slirp->last_slowtimo = curtime;
 545    }
 546
 547    /*
 548     * Check sockets
 549     */
 550    if (!select_error) {
 551        /*
 552         * Check TCP sockets
 553         */
 554        for (so = slirp->tcb.so_next; so != &slirp->tcb;
 555             so = so_next) {
 556            int revents;
 557
 558            so_next = so->so_next;
 559
 560            revents = 0;
 561            if (so->pollfds_idx != -1) {
 562                revents = get_revents(so->pollfds_idx, opaque);
 563            }
 564
 565            if (so->so_state & SS_NOFDREF || so->s == -1) {
 566                continue;
 567            }
 568
 569            /*
 570             * Check for URG data
 571             * This will soread as well, so no need to
 572             * test for SLIRP_POLL_IN below if this succeeds
 573             */
 574            if (revents & SLIRP_POLL_PRI) {
 575                ret = sorecvoob(so);
 576                if (ret < 0) {
 577                    /* Socket error might have resulted in the socket being
 578                     * removed, do not try to do anything more with it. */
 579                    continue;
 580                }
 581            }
 582            /*
 583             * Check sockets for reading
 584             */
 585            else if (revents &
 586                     (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR)) {
 587                /*
 588                 * Check for incoming connections
 589                 */
 590                if (so->so_state & SS_FACCEPTCONN) {
 591                    tcp_connect(so);
 592                    continue;
 593                } /* else */
 594                ret = soread(so);
 595
 596                /* Output it if we read something */
 597                if (ret > 0) {
 598                    tcp_output(sototcpcb(so));
 599                }
 600                if (ret < 0) {
 601                    /* Socket error might have resulted in the socket being
 602                     * removed, do not try to do anything more with it. */
 603                    continue;
 604                }
 605            }
 606
 607            /*
 608             * Check sockets for writing
 609             */
 610            if (!(so->so_state & SS_NOFDREF) &&
 611                (revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) {
 612                /*
 613                 * Check for non-blocking, still-connecting sockets
 614                 */
 615                if (so->so_state & SS_ISFCONNECTING) {
 616                    /* Connected */
 617                    so->so_state &= ~SS_ISFCONNECTING;
 618
 619                    ret = send(so->s, (const void *) &ret, 0, 0);
 620                    if (ret < 0) {
 621                        /* XXXXX Must fix, zero bytes is a NOP */
 622                        if (errno == EAGAIN || errno == EWOULDBLOCK ||
 623                            errno == EINPROGRESS || errno == ENOTCONN) {
 624                            continue;
 625                        }
 626
 627                        /* else failed */
 628                        so->so_state &= SS_PERSISTENT_MASK;
 629                        so->so_state |= SS_NOFDREF;
 630                    }
 631                    /* else so->so_state &= ~SS_ISFCONNECTING; */
 632
 633                    /*
 634                     * Continue tcp_input
 635                     */
 636                    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
 637                              so->so_ffamily);
 638                    /* continue; */
 639                } else {
 640                    ret = sowrite(so);
 641                    if (ret > 0) {
 642                        /* Call tcp_output in case we need to send a window
 643                         * update to the guest, otherwise it will be stuck
 644                         * until it sends a window probe. */
 645                        tcp_output(sototcpcb(so));
 646                    }
 647                }
 648            }
 649        }
 650
 651        /*
 652         * Now UDP sockets.
 653         * Incoming packets are sent straight away, they're not buffered.
 654         * Incoming UDP data isn't buffered either.
 655         */
 656        for (so = slirp->udb.so_next; so != &slirp->udb;
 657             so = so_next) {
 658            int revents;
 659
 660            so_next = so->so_next;
 661
 662            revents = 0;
 663            if (so->pollfds_idx != -1) {
 664                revents = get_revents(so->pollfds_idx, opaque);
 665            }
 666
 667            if (so->s != -1 &&
 668                (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
 669                sorecvfrom(so);
 670            }
 671        }
 672
 673        /*
 674         * Check incoming ICMP relies.
 675         */
 676        for (so = slirp->icmp.so_next; so != &slirp->icmp;
 677             so = so_next) {
 678            int revents;
 679
 680            so_next = so->so_next;
 681
 682            revents = 0;
 683            if (so->pollfds_idx != -1) {
 684                revents = get_revents(so->pollfds_idx, opaque);
 685            }
 686
 687            if (so->s != -1 &&
 688                (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
 689                icmp_receive(so);
 690            }
 691        }
 692    }
 693
 694    if_start(slirp);
 695}
 696
 697static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
 698{
 699    struct slirp_arphdr *ah = (struct slirp_arphdr *)(pkt + ETH_HLEN);
 700    uint8_t arp_reply[MAX(ETH_HLEN + sizeof(struct slirp_arphdr), 64)];
 701    struct ethhdr *reh = (struct ethhdr *)arp_reply;
 702    struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
 703    int ar_op;
 704    struct gfwd_list *ex_ptr;
 705
 706    if (!slirp->in_enabled) {
 707        return;
 708    }
 709
 710    ar_op = ntohs(ah->ar_op);
 711    switch(ar_op) {
 712    case ARPOP_REQUEST:
 713        if (ah->ar_tip == ah->ar_sip) {
 714            /* Gratuitous ARP */
 715            arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
 716            return;
 717        }
 718
 719        if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
 720            slirp->vnetwork_addr.s_addr) {
 721            if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
 722                ah->ar_tip == slirp->vhost_addr.s_addr)
 723                goto arp_ok;
 724            /* TODO: IPv6 */
 725            for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
 726                if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
 727                    goto arp_ok;
 728            }
 729            return;
 730        arp_ok:
 731            memset(arp_reply, 0, sizeof(arp_reply));
 732
 733            arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
 734
 735            /* ARP request for alias/dns mac address */
 736            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
 737            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
 738            memcpy(&reh->h_source[2], &ah->ar_tip, 4);
 739            reh->h_proto = htons(ETH_P_ARP);
 740
 741            rah->ar_hrd = htons(1);
 742            rah->ar_pro = htons(ETH_P_IP);
 743            rah->ar_hln = ETH_ALEN;
 744            rah->ar_pln = 4;
 745            rah->ar_op = htons(ARPOP_REPLY);
 746            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
 747            rah->ar_sip = ah->ar_tip;
 748            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
 749            rah->ar_tip = ah->ar_sip;
 750            slirp_send_packet_all(slirp, arp_reply, sizeof(arp_reply));
 751        }
 752        break;
 753    case ARPOP_REPLY:
 754        arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
 755        break;
 756    default:
 757        break;
 758    }
 759}
 760
 761void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
 762{
 763    struct mbuf *m;
 764    int proto;
 765
 766    if (pkt_len < ETH_HLEN)
 767        return;
 768
 769    proto = (((uint16_t) pkt[12]) << 8) + pkt[13];
 770    switch(proto) {
 771    case ETH_P_ARP:
 772        arp_input(slirp, pkt, pkt_len);
 773        break;
 774    case ETH_P_IP:
 775    case ETH_P_IPV6:
 776        m = m_get(slirp);
 777        if (!m)
 778            return;
 779        /* Note: we add 2 to align the IP header on 4 bytes,
 780         * and add the margin for the tcpiphdr overhead  */
 781        if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) {
 782            m_inc(m, pkt_len + TCPIPHDR_DELTA + 2);
 783        }
 784        m->m_len = pkt_len + TCPIPHDR_DELTA + 2;
 785        memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len);
 786
 787        m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN;
 788        m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN;
 789
 790        if (proto == ETH_P_IP) {
 791            ip_input(m);
 792        } else if (proto == ETH_P_IPV6) {
 793            ip6_input(m);
 794        }
 795        break;
 796
 797    case ETH_P_NCSI:
 798        ncsi_input(slirp, pkt, pkt_len);
 799        break;
 800
 801    default:
 802        break;
 803    }
 804}
 805
 806/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no
 807 * packet should be sent, 0 if the packet must be re-queued, 2 if the packet
 808 * is ready to go.
 809 */
 810static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
 811        uint8_t ethaddr[ETH_ALEN])
 812{
 813    const struct ip *iph = (const struct ip *)ifm->m_data;
 814
 815    if (iph->ip_dst.s_addr == 0) {
 816        /* 0.0.0.0 can not be a destination address, something went wrong,
 817         * avoid making it worse */
 818        return 1;
 819    }
 820    if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
 821        uint8_t arp_req[ETH_HLEN + sizeof(struct slirp_arphdr)];
 822        struct ethhdr *reh = (struct ethhdr *)arp_req;
 823        struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + ETH_HLEN);
 824
 825        if (!ifm->resolution_requested) {
 826            /* If the client addr is not known, send an ARP request */
 827            memset(reh->h_dest, 0xff, ETH_ALEN);
 828            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
 829            memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
 830            reh->h_proto = htons(ETH_P_ARP);
 831            rah->ar_hrd = htons(1);
 832            rah->ar_pro = htons(ETH_P_IP);
 833            rah->ar_hln = ETH_ALEN;
 834            rah->ar_pln = 4;
 835            rah->ar_op = htons(ARPOP_REQUEST);
 836
 837            /* source hw addr */
 838            memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
 839            memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
 840
 841            /* source IP */
 842            rah->ar_sip = slirp->vhost_addr.s_addr;
 843
 844            /* target hw addr (none) */
 845            memset(rah->ar_tha, 0, ETH_ALEN);
 846
 847            /* target IP */
 848            rah->ar_tip = iph->ip_dst.s_addr;
 849            slirp->client_ipaddr = iph->ip_dst;
 850            slirp_send_packet_all(slirp, arp_req, sizeof(arp_req));
 851            ifm->resolution_requested = true;
 852
 853            /* Expire request and drop outgoing packet after 1 second */
 854            ifm->expiration_date =
 855                slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
 856        }
 857        return 0;
 858    } else {
 859        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
 860        /* XXX: not correct */
 861        memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
 862        eh->h_proto = htons(ETH_P_IP);
 863
 864        /* Send this */
 865        return 2;
 866    }
 867}
 868
 869/* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no
 870 * packet should be sent, 0 if the packet must be re-queued, 2 if the packet
 871 * is ready to go.
 872 */
 873static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
 874        uint8_t ethaddr[ETH_ALEN])
 875{
 876    const struct ip6 *ip6h = mtod(ifm, const struct ip6 *);
 877    if (!ndp_table_search(slirp, ip6h->ip_dst, ethaddr)) {
 878        if (!ifm->resolution_requested) {
 879            ndp_send_ns(slirp, ip6h->ip_dst);
 880            ifm->resolution_requested = true;
 881            ifm->expiration_date = slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
 882        }
 883        return 0;
 884    } else {
 885        eh->h_proto = htons(ETH_P_IPV6);
 886        in6_compute_ethaddr(ip6h->ip_src, eh->h_source);
 887
 888        /* Send this */
 889        return 2;
 890    }
 891}
 892
 893/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
 894 * re-queued.
 895 */
 896int if_encap(Slirp *slirp, struct mbuf *ifm)
 897{
 898    uint8_t buf[1600];
 899    struct ethhdr *eh = (struct ethhdr *)buf;
 900    uint8_t ethaddr[ETH_ALEN];
 901    const struct ip *iph = (const struct ip *)ifm->m_data;
 902    int ret;
 903
 904    if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
 905        return 1;
 906    }
 907
 908    switch (iph->ip_v) {
 909    case IPVERSION:
 910        ret = if_encap4(slirp, ifm, eh, ethaddr);
 911        if (ret < 2) {
 912            return ret;
 913        }
 914        break;
 915
 916    case IP6VERSION:
 917        ret = if_encap6(slirp, ifm, eh, ethaddr);
 918        if (ret < 2) {
 919            return ret;
 920        }
 921        break;
 922
 923    default:
 924        g_assert_not_reached();
 925        break;
 926    }
 927
 928    memcpy(eh->h_dest, ethaddr, ETH_ALEN);
 929    DEBUG_ARG("src = %02x:%02x:%02x:%02x:%02x:%02x",
 930              eh->h_source[0], eh->h_source[1], eh->h_source[2],
 931              eh->h_source[3], eh->h_source[4], eh->h_source[5]);
 932    DEBUG_ARG("dst = %02x:%02x:%02x:%02x:%02x:%02x",
 933              eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
 934              eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]);
 935    memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
 936    slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN);
 937    return 1;
 938}
 939
 940/* Drop host forwarding rule, return 0 if found. */
 941/* TODO: IPv6 */
 942int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
 943                         int host_port)
 944{
 945    struct socket *so;
 946    struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
 947    struct sockaddr_in addr;
 948    int port = htons(host_port);
 949    socklen_t addr_len;
 950
 951    for (so = head->so_next; so != head; so = so->so_next) {
 952        addr_len = sizeof(addr);
 953        if ((so->so_state & SS_HOSTFWD) &&
 954            getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
 955            addr.sin_addr.s_addr == host_addr.s_addr &&
 956            addr.sin_port == port) {
 957            so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
 958            closesocket(so->s);
 959            sofree(so);
 960            return 0;
 961        }
 962    }
 963
 964    return -1;
 965}
 966
 967/* TODO: IPv6 */
 968int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
 969                      int host_port, struct in_addr guest_addr, int guest_port)
 970{
 971    if (!guest_addr.s_addr) {
 972        guest_addr = slirp->vdhcp_startaddr;
 973    }
 974    if (is_udp) {
 975        if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
 976                        guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
 977            return -1;
 978    } else {
 979        if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
 980                        guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
 981            return -1;
 982    }
 983    return 0;
 984}
 985
 986/* TODO: IPv6 */
 987static bool
 988check_guestfwd(Slirp *slirp, struct in_addr *guest_addr, int guest_port)
 989{
 990    struct gfwd_list *tmp_ptr;
 991
 992    if (!guest_addr->s_addr) {
 993        guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
 994            (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
 995    }
 996    if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
 997        slirp->vnetwork_addr.s_addr ||
 998        guest_addr->s_addr == slirp->vhost_addr.s_addr ||
 999        guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
1000        return false;
1001    }
1002
1003    /* check if the port is "bound" */
1004    for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
1005        if (guest_port == tmp_ptr->ex_fport &&
1006            guest_addr->s_addr == tmp_ptr->ex_addr.s_addr)
1007            return false;
1008    }
1009
1010    return true;
1011}
1012
1013int slirp_add_exec(Slirp *slirp, const char *cmdline,
1014                   struct in_addr *guest_addr, int guest_port)
1015{
1016    if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1017        return -1;
1018    }
1019
1020    add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port));
1021    return 0;
1022}
1023
1024int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
1025                       struct in_addr *guest_addr, int guest_port)
1026{
1027    if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1028        return -1;
1029    }
1030
1031    add_guestfwd(&slirp->guestfwd_list, write_cb, opaque,
1032                 *guest_addr, htons(guest_port));
1033    return 0;
1034}
1035
1036ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
1037{
1038    if (so->s == -1 && so->guestfwd) {
1039        /* XXX this blocks entire thread. Rewrite to use
1040         * qemu_chr_fe_write and background I/O callbacks */
1041        so->guestfwd->write_cb(buf, len, so->guestfwd->opaque);
1042        return len;
1043    }
1044
1045    if (so->s == -1) {
1046        /*
1047         * This should in theory not happen but it is hard to be
1048         * sure because some code paths will end up with so->s == -1
1049         * on a failure but don't dispose of the struct socket.
1050         * Check specifically, so we don't pass -1 to send().
1051         */
1052        errno = EBADF;
1053        return -1;
1054    }
1055
1056    return send(so->s, buf, len, flags);
1057}
1058
1059struct socket *
1060slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
1061{
1062    struct socket *so;
1063
1064    /* TODO: IPv6 */
1065    for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
1066        if (so->so_faddr.s_addr == guest_addr.s_addr &&
1067            htons(so->so_fport) == guest_port) {
1068            return so;
1069        }
1070    }
1071    return NULL;
1072}
1073
1074size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
1075                             int guest_port)
1076{
1077    struct iovec iov[2];
1078    struct socket *so;
1079
1080    so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1081
1082    if (!so || so->so_state & SS_NOFDREF) {
1083        return 0;
1084    }
1085
1086    if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2)) {
1087        return 0;
1088    }
1089
1090    return sopreprbuf(so, iov, NULL);
1091}
1092
1093void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
1094                       const uint8_t *buf, int size)
1095{
1096    int ret;
1097    struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1098
1099    if (!so)
1100        return;
1101
1102    ret = soreadbuf(so, (const char *)buf, size);
1103
1104    if (ret > 0)
1105        tcp_output(sototcpcb(so));
1106}
1107
1108void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len)
1109{
1110    ssize_t ret = slirp->cb->send_packet(buf, len, slirp->opaque);
1111
1112    if (ret < 0) {
1113        g_critical("Failed to send packet, ret: %ld", (long) ret);
1114    } else if (ret < len) {
1115        DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu",
1116                (long) ret, (unsigned long) len);
1117    }
1118}
1119