~ubuntu-branches/ubuntu/oneiric/virtualbox/oneiric-updates

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Network/slirp/slirp.c

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2011-09-02 11:50:47 UTC
  • mfrom: (3.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20110902115047-kfhmsikrpydgyoji
Tags: 4.1.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox.files/source_virtualbox.py
    - debian/virtualbox.install
  - Drop *-source packages.
  - Add vboxguest modalias the to the package control field.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: slirp.c 38044 2011-07-19 04:52:49Z vboxsync $ */
 
1
/* $Id: slirp.c 38170 2011-07-26 04:50:31Z vboxsync $ */
2
2
/** @file
3
3
 * NAT - slirp glue.
4
4
 */
587
587
{
588
588
    int fNATfailed = 0;
589
589
    int rc;
590
 
    PNATState pData = RTMemAllocZ(RT_ALIGN_Z(sizeof(NATState), sizeof(uint64_t)));
 
590
    PNATState pData;
 
591
    if (u32Netmask & 0x1f)
 
592
        /* CTL is x.x.x.15, bootp passes up to 16 IPs (15..31) */
 
593
        return VERR_INVALID_PARAMETER;
 
594
    pData = RTMemAllocZ(RT_ALIGN_Z(sizeof(NATState), sizeof(uint64_t)));
591
595
    *ppData = pData;
592
596
    if (!pData)
593
597
        return VERR_NO_MEMORY;
594
 
    if (u32Netmask & 0x1f)
595
 
        /* CTL is x.x.x.15, bootp passes up to 16 IPs (15..31) */
596
 
        return VERR_INVALID_PARAMETER;
597
598
    pData->fPassDomain = !fUseHostResolver ? fPassDomain : false;
598
599
    pData->fUseHostResolver = fUseHostResolver;
599
600
    pData->pvUser = pvUser;
604
605
    pData->socket_snd = 64 * _1K;
605
606
    tcp_sndspace = 64 * _1K;
606
607
    tcp_rcvspace = 64 * _1K;
 
608
    pData->soMaxConn = 1; /* historical value */
607
609
 
608
610
#ifdef RT_OS_WINDOWS
609
611
    {
622
624
    link_up = 1;
623
625
 
624
626
    rc = bootp_dhcp_init(pData);
625
 
    if (rc != 0)
 
627
    if (RT_FAILURE(rc))
626
628
    {
627
 
        Log(("NAT: DHCP server initialization was failed\n"));
628
 
        return VINF_NAT_DNS;
 
629
        Log(("NAT: DHCP server initialization failed\n"));
 
630
        RTMemFree(pData);
 
631
        *ppData = NULL;
 
632
        return rc;
629
633
    }
630
634
    debug_init();
631
635
    if_init(pData);
940
944
        {
941
945
            Log2(("connecting %R[natsock] engaged\n",so));
942
946
            STAM_COUNTER_INC(&pData->StatTCPHot);
943
 
#ifndef NAT_CONNECT_EXPERIMENT
944
 
            TCP_ENGAGE_EVENT1(so, writefds);
945
 
#else
946
 
# ifdef RT_OS_WINDOWS
 
947
#ifdef RT_OS_WINDOWS
947
948
            WIN_TCP_ENGAGE_EVENT2(so, writefds, connectfds);
948
 
# else
 
949
#else
949
950
            TCP_ENGAGE_EVENT1(so, writefds);
950
 
# endif
951
951
#endif
952
952
        }
953
953
 
966
966
         * receive more, and we have room for it XXX /2 ?
967
967
         */
968
968
        /* @todo: vvl - check which predicat here will be more useful here in rerm of new sbufs. */
969
 
        if (CONN_CANFRCV(so) && (SBUF_LEN(&so->so_snd) < (SBUF_SIZE(&so->so_snd)/2)))
 
969
        if (   CONN_CANFRCV(so)
 
970
            && (SBUF_LEN(&so->so_snd) < (SBUF_SIZE(&so->so_snd)/2))
 
971
#ifdef RT_OS_WINDOWS
 
972
            && !(so->so_state & SS_ISFCONNECTING)
 
973
#endif
 
974
        )
970
975
        {
971
976
            STAM_COUNTER_INC(&pData->StatTCPHot);
972
977
            TCP_ENGAGE_EVENT2(so, readfds, xfds);
1038
1043
    STAM_PROFILE_STOP(&pData->StatFill, a);
1039
1044
}
1040
1045
 
 
1046
 
 
1047
static bool slirpConnectOrWrite(PNATState pData, struct socket *so, bool fConnectOnly)
 
1048
{
 
1049
    int ret;
 
1050
    LogFlowFunc(("ENTER: so:%R[natsock], fConnectOnly:%RTbool\n", so, fConnectOnly));
 
1051
    /*
 
1052
     * Check for non-blocking, still-connecting sockets
 
1053
     */
 
1054
    if (so->so_state & SS_ISFCONNECTING)
 
1055
    {
 
1056
        Log2(("connecting %R[natsock] catched\n", so));
 
1057
        /* Connected */
 
1058
        so->so_state &= ~SS_ISFCONNECTING;
 
1059
 
 
1060
        /*
 
1061
         * This should be probably guarded by PROBE_CONN too. Anyway,
 
1062
         * we disable it on OS/2 because the below send call returns
 
1063
         * EFAULT which causes the opened TCP socket to close right
 
1064
         * after it has been opened and connected.
 
1065
         */
 
1066
#ifndef RT_OS_OS2
 
1067
    ret = send(so->s, (const char *)&ret, 0, 0);
 
1068
    if (ret < 0)
 
1069
    {
 
1070
        /* XXXXX Must fix, zero bytes is a NOP */
 
1071
        if (   errno == EAGAIN
 
1072
            || errno == EWOULDBLOCK
 
1073
            || errno == EINPROGRESS
 
1074
            || errno == ENOTCONN)
 
1075
        {
 
1076
            LogFlowFunc(("LEAVE: true"));
 
1077
            return false;
 
1078
        }
 
1079
 
 
1080
        /* else failed */
 
1081
        so->so_state = SS_NOFDREF;
 
1082
    }
 
1083
    /* else so->so_state &= ~SS_ISFCONNECTING; */
 
1084
#endif
 
1085
 
 
1086
        /*
 
1087
         * Continue tcp_input
 
1088
         */
 
1089
        TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
 
1090
        /* continue; */
 
1091
    }
 
1092
    else if (!fConnectOnly)
 
1093
        SOWRITE(ret, pData, so);
 
1094
    /*
 
1095
     * XXX If we wrote something (a lot), there could be the need
 
1096
     * for a window update. In the worst case, the remote will send
 
1097
     * a window probe to get things going again.
 
1098
     */
 
1099
    LogFlowFunc(("LEAVE: true"));
 
1100
    return true;
 
1101
}
 
1102
 
1041
1103
#if defined(RT_OS_WINDOWS)
1042
1104
void slirp_select_poll(PNATState pData, int fTimeout, int fIcmp)
1043
1105
#else /* RT_OS_WINDOWS */
1163
1225
             */
1164
1226
            &&  !CHECK_FD_SET(so, NetworkEvents, closefds)
1165
1227
#endif
1166
 
#ifdef NAT_CONNECT_EXPERIMENT
1167
 
# ifdef RT_OS_WINDOWS
 
1228
#ifdef RT_OS_WINDOWS
1168
1229
            /**
1169
 
             * In some cases FD_CONNECT comes with FD_OOB, that confuse tcp processing.
 
1230
             * In some cases FD_CLOSE comes with FD_OOB, that confuse tcp processing.
1170
1231
             */
1171
 
            && !WIN_CHECK_FD_SET(so, NetworkEvents, connectfds)
1172
 
# endif
 
1232
            && !WIN_CHECK_FD_SET(so, NetworkEvents, closefds)
1173
1233
#endif
1174
1234
        )
1175
1235
        {
1182
1242
        else if (   CHECK_FD_SET(so, NetworkEvents, readfds)
1183
1243
                 || WIN_CHECK_FD_SET(so, NetworkEvents, acceptds))
1184
1244
        {
1185
 
#ifdef DEBUG_vvl
1186
 
            Assert(((so->so_state & SS_ISFCONNECTING) == 0));
 
1245
 
 
1246
#ifdef RT_OS_WINDOWS
 
1247
            if (WIN_CHECK_FD_SET(so, NetworkEvents, connectfds))
 
1248
            {
 
1249
                /* Finish connection first */
 
1250
                /* should we ignore return value? */
 
1251
                bool fRet = slirpConnectOrWrite(pData, so, true);
 
1252
                LogFunc(("fRet:%RTbool\n", fRet));
 
1253
            }
1187
1254
#endif
1188
1255
            /*
1189
1256
             * Check for incoming connections
1237
1304
         * Check sockets for writing
1238
1305
         */
1239
1306
        if (    CHECK_FD_SET(so, NetworkEvents, writefds)
1240
 
#if defined(NAT_CONNECT_EXPERIMENT)
 
1307
#ifdef RT_OS_WINDOWS
1241
1308
            ||  WIN_CHECK_FD_SET(so, NetworkEvents, connectfds)
1242
1309
#endif
1243
1310
            )
1244
1311
        {
1245
 
            /*
1246
 
             * Check for non-blocking, still-connecting sockets
1247
 
             */
1248
 
            if (so->so_state & SS_ISFCONNECTING)
1249
 
            {
1250
 
                Log2(("connecting %R[natsock] catched\n", so));
1251
 
                /* Connected */
1252
 
                so->so_state &= ~SS_ISFCONNECTING;
1253
 
 
1254
 
                /*
1255
 
                 * This should be probably guarded by PROBE_CONN too. Anyway,
1256
 
                 * we disable it on OS/2 because the below send call returns
1257
 
                 * EFAULT which causes the opened TCP socket to close right
1258
 
                 * after it has been opened and connected.
1259
 
                 */
1260
 
#ifndef RT_OS_OS2
1261
 
                ret = send(so->s, (const char *)&ret, 0, 0);
1262
 
                if (ret < 0)
1263
 
                {
1264
 
                    /* XXXXX Must fix, zero bytes is a NOP */
1265
 
                    if (   errno == EAGAIN
1266
 
                        || errno == EWOULDBLOCK
1267
 
                        || errno == EINPROGRESS
1268
 
                        || errno == ENOTCONN)
1269
 
                        CONTINUE(tcp);
1270
 
 
1271
 
                    /* else failed */
1272
 
                    so->so_state = SS_NOFDREF;
1273
 
                }
1274
 
                /* else so->so_state &= ~SS_ISFCONNECTING; */
1275
 
#endif
1276
 
 
1277
 
                /*
1278
 
                 * Continue tcp_input
1279
 
                 */
1280
 
                TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
1281
 
                /* continue; */
1282
 
            }
1283
 
            else
1284
 
                SOWRITE(ret, pData, so);
1285
 
            /*
1286
 
             * XXX If we wrote something (a lot), there could be the need
1287
 
             * for a window update. In the worst case, the remote will send
1288
 
             * a window probe to get things going again.
1289
 
             */
 
1312
            if(!slirpConnectOrWrite(pData, so, false))
 
1313
                CONTINUE(tcp);
1290
1314
        }
1291
1315
 
1292
1316
        /*
1591
1615
    uint8_t *mbuf = NULL;
1592
1616
    size_t mlen = 0;
1593
1617
    STAM_PROFILE_START(&pData->StatIF_encap, a);
 
1618
    LogFlowFunc(("ENTER: pData:%p, eth_proto:%RX16, m:%p, flags:%d\n",
 
1619
                pData, eth_proto, m, flags));
1594
1620
 
1595
1621
    M_ASSERTPKTHDR(m);
1596
1622
    m->m_data -= ETH_HLEN;
1631
1657
    }
1632
1658
    mbuf = mtod(m, uint8_t *);
1633
1659
    eh->h_proto = RT_H2N_U16(eth_proto);
 
1660
    LogFunc(("eh(dst:%RTmac, src:%RTmac)\n", eh->h_dest, eh->h_source));
1634
1661
    if (flags & ETH_ENCAP_URG)
1635
1662
        slirp_urg_output(pData->pvUser, m, mbuf, mlen);
1636
1663
    else
1637
1664
        slirp_output(pData->pvUser, m, mbuf, mlen);
1638
1665
done:
1639
1666
    STAM_PROFILE_STOP(&pData->StatIF_encap, a);
 
1667
    LogFlowFuncLeave();
1640
1668
}
1641
1669
 
1642
1670
/**
1965
1993
            LogRel(("NAT: (" #name ":%d)\n", (val)));                               \
1966
1994
    } while (0)
1967
1995
 
 
1996
void slirp_set_somaxconn(PNATState pData, int iSoMaxConn)
 
1997
{
 
1998
    LogFlowFunc(("iSoMaxConn:d\n", iSoMaxConn));
 
1999
    if (iSoMaxConn > SOMAXCONN)
 
2000
    {
 
2001
        LogRel(("New value of somaxconn(%d) bigger than SOMAXCONN(%d)\n", iSoMaxConn, SOMAXCONN));
 
2002
        pData->soMaxConn = SOMAXCONN;
 
2003
    }
 
2004
    pData->soMaxConn = iSoMaxConn > 0 ? iSoMaxConn : pData->soMaxConn;
 
2005
    LogRel(("New value of somaxconn: %d\n", pData->soMaxConn));
 
2006
    LogFlowFuncLeave();
 
2007
}
1968
2008
/* don't allow user set less 8kB and more than 1M values */
1969
2009
#define _8K_1M_CHECK_ARG(name, val) CHECK_ARG(name, (val), 8, 1024)
1970
2010
void slirp_set_rcvbuf(PNATState pData, int kilobytes)
2044
2084
    struct mbuf *m;
2045
2085
    struct ethhdr *ehdr;
2046
2086
    struct arphdr *ahdr;
 
2087
    LogFlowFunc(("ENTER: %RTnaipv4\n", dst));
2047
2088
 
2048
2089
    m = m_getcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR);
2049
2090
    if (m == NULL)
2050
2091
    {
2051
2092
        Log(("NAT: Can't alloc mbuf for ARP request\n"));
 
2093
        LogFlowFuncLeave();
2052
2094
        return;
2053
2095
    }
2054
2096
    ehdr = mtod(m, struct ethhdr *);
2070
2112
    m->m_data += ETH_HLEN;
2071
2113
    m->m_len -= ETH_HLEN;
2072
2114
    if_encap(pData, ETH_P_ARP, m, ETH_ENCAP_URG);
 
2115
    LogFlowFuncLeave();
2073
2116
}
2074
2117
 
2075
2118
/* updates the arp cache