VirtualBox

Changeset 27399 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Mar 16, 2010 1:06:51 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
58861
Message:

NAT: the 2-step ICMP read has been introduced. Mbuf destination capacity extends up to required size before copy.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/socket.c

    r26598 r27399  
    10531053    uint8_t proto;
    10541054    int type = 0;
     1055    int m_room;
    10551056
    10561057    ip = (struct ip *)buff;
     
    11051106    original_hlen = ip->ip_hl << 2;
    11061107    /* saves original ip header and options */
    1107     memcpy(m->m_data + original_hlen, buff + hlen, len - hlen);
     1108    /* m_room space in the saved m buffer */
     1109    m_room = m->m_len + M_TRAILINGSPACE(m) - original_hlen;
     1110    if (m_room >= len - hlen)
     1111        memcpy(m->m_data + original_hlen, buff + hlen, len - hlen);
     1112    else
     1113    {
     1114        m_inc(m, len); /*increase the room of the mbuf up to len*/
     1115        memcpy(m->m_data + original_hlen, buff + hlen, len - hlen);
     1116    }
    11081117#ifndef VBOX_WITH_SLIRP_BSD_MBUF
    11091118    m->m_len = len - hlen + original_hlen;
     
    12711280    struct sockaddr_in addr;
    12721281    socklen_t addrlen = sizeof(struct sockaddr_in);
     1282    struct ip ip;
    12731283    char *buff;
    12741284    int len = 0;
    1275     int rc = 0;
    1276     static int signalled = 0;
    1277 
    1278     rc = ioctlsocket(so->s, FIONREAD, &len);
    1279     if (   rc == -1
     1285
     1286    /* 1- step: read the ip header */
     1287    len = recvfrom(so->s, &ip, sizeof(struct ip), MSG_PEEK,
     1288                   (struct sockaddr *)&addr, &addrlen);
     1289    if (   len < 0
    12801290        && (   errno == EAGAIN
    12811291            || errno == EWOULDBLOCK
     
    12831293            || errno == ENOTCONN))
    12841294    {
     1295        Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm (would block)\n"));
    12851296        return;
    12861297    }
    1287     if (rc == -1 && signalled == 0)
    1288     {
    1289         signalled = 1;
    1290         LogRel(("NAT: fetching number of bits has been failed for ICMP socket (%d: %s)\n",
    1291             errno, strerror(errno)));
    1292         return;
    1293     }
    1294     len = (len != 0 && rc != -1 ? len : 1500);
    1295     buff = RTMemAlloc(len);
    1296     len = recvfrom(so->s, buff, len, 0,
    1297                    (struct sockaddr *)&addr, &addrlen);
    1298     /* XXX Check if reply is "correct"? */
    1299 
    1300     if (len == -1 || len == 0)
     1298
     1299    if (   len < sizeof(struct ip)
     1300        || len < 0
     1301        || len == 0)
    13011302    {
    13021303        u_char code;
    1303         if (   len == -1
    1304             && (errno == EAGAIN
    1305             || errno == EWOULDBLOCK
    1306             || errno == EINPROGRESS
    1307             || errno == ENOTCONN))
    1308         {
    1309             return;
    1310         }
    13111304        code = ICMP_UNREACH_PORT;
    13121305
     
    13201313        icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
    13211314        so->so_m = NULL;
    1322     }
    1323     else
    1324     {
    1325         send_icmp_to_guest(pData, buff, len, so, &addr);
    1326     }
     1315        Log(("sorecvfrom_icmp_unix: 1 - step can't read IP datagramm \n"));
     1316        return;
     1317    }
     1318    /* basic check of IP header */
     1319    if (   ip.ip_v != IPVERSION
     1320        || ip.ip_p != IPPROTO_ICMP)
     1321    {
     1322        Log(("sorecvfrom_icmp_unix: 1 - step IP isn't IPv4 \n"));
     1323        return;
     1324    }
     1325
     1326    len = RT_N2H_U16(ip.ip_len);
     1327    buff = RTMemAlloc(len);
     1328    if (buff == NULL)
     1329    {
     1330        Log(("sorecvfrom_icmp_unix: 1 - step can't allocate enought room for datagram\n"));
     1331        return;
     1332    }
     1333    /* 2 - step: we're reading rest of the datagramm to the buffer */
     1334    addrlen = sizeof(struct sockaddr_in);
     1335    memset(&addr, 0, addrlen);
     1336    len = recvfrom(so->s, buff, len, 0,
     1337                   (struct sockaddr *)&addr, &addrlen);
     1338    if (   len < 0
     1339        && (   errno == EAGAIN
     1340            || errno == EWOULDBLOCK
     1341            || errno == EINPROGRESS
     1342            || errno == ENOTCONN))
     1343    {
     1344        Log(("sorecvfrom_icmp_unix: 2 - step can't read IP body (would block expected:%d)\n",
     1345            RT_N2H_U16(ip.ip_len)));
     1346        RTMemFree(buff);
     1347        return;
     1348    }
     1349    if (   len < 0
     1350        || len < (RT_N2H_U16(ip.ip_len))
     1351        || len == 0)
     1352    {
     1353        Log(("sorecvfrom_icmp_unix: 2 - step read of the rest of datagramm is fallen (errno:%d, len:%d expected: %d)\n",
     1354             errno, len, (RT_N2H_U16(ip.ip_len) - sizeof(struct ip))));
     1355        RTMemFree(buff);
     1356        return;
     1357    }
     1358    /* len is modified in 2nd read, when the rest of the datagramm was read */
     1359    send_icmp_to_guest(pData, buff, len, so, &addr);
    13271360    RTMemFree(buff);
    13281361}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette