VirtualBox

Ignore:
Timestamp:
Jun 23, 2010 3:52:15 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
63019
Message:

NAT: icmp_input releasing mbuf and intermediate buffer.

File:
1 edited

Legend:

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

    r30366 r30399  
    330330{
    331331    register struct icmp *icp;
     332    int fIcpOnMbuf = 1; /* if icp pointer to m->m_data */
    332333    register struct ip *ip = mtod(m, struct ip *);
    333334    int icmplen = ip->ip_len;
     
    354355        /* min 8 bytes payload */
    355356        icmpstat.icps_tooshort++;
    356 freeit:
    357         m_freem(pData, m);
    358357        goto end_error;
    359358    }
     
    361360    m->m_len -= hlen;
    362361    m->m_data += hlen;
     362
     363    if (cksum(m, icmplen))
     364    {
     365        icmpstat.icps_checksum++;
     366        goto end_error;
     367    }
     368
    363369    if (m->m_next != NULL)
    364370    {
    365371        char *buf = RTMemAlloc(icmplen);
     372        if (!buf)
     373        {
     374            LogRel(("NAT: not enought memory to allocate the buffer\n"));
     375            goto end_error;
     376        }
    366377        m_copydata(m, 0, icmplen, buf);
    367378        icp = (struct icmp *)buf;
     379        fIcpOnMbuf = 0;
    368380    }
    369381    else
    370     {
    371382        icp = mtod(m, struct icmp *);
    372     }
    373     if (cksum(m, icmplen))
    374     {
    375         icmpstat.icps_checksum++;
    376         goto freeit;
    377     }
     383
     384
    378385    m->m_len += hlen;
    379386    m->m_data -= hlen;
     
    394401                ip->ip_src.s_addr = dst;
    395402                icmp_reflect(pData, m);
     403                if (!fIcpOnMbuf)
     404                    RTMemFree(icp);
     405                return;
    396406            }
    397407            else
     
    421431                {
    422432                    ssize_t rc;
    423                     m->m_so = &pData->icmp_socket;
    424                     icmp_attach(pData, m);
    425433                    ttl = ip->ip_ttl;
    426434                    Log(("NAT/ICMP: try to set TTL(%d)\n", ttl));
     
    432440                    rc = sendto(pData->icmp_socket.s, icp, icmplen, 0,
    433441                              (struct sockaddr *)&addr, sizeof(addr));
    434                     if (rc < 0)
     442                    if (rc >= 0)
    435443                    {
    436                         LogRel((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
    437                                     errno, strerror(errno)));
    438                         icmp_error(pData, m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
     444                        icmp_attach(pData, m);
     445                        m->m_so = &pData->icmp_socket;
     446                        /* don't let m_freem at the end free atached buffer */
     447                        return;
    439448                    }
    440                 }
    441                 else
    442                 {
    443                     /*
    444                      * We're freeing the ICMP message, which unable sent or process.
    445                      * That behavior described in rfc 793, we shouldn't notify sender about
    446                      * fail of processing it's ICMP packets
    447                      */
    448                     m_freem(pData, m);
    449                     return;
     449                   
     450                    LogRel((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
     451                                errno, strerror(errno)));
     452                    icmp_error(pData, m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
    450453                }
    451454#else /* RT_OS_WINDOWS */
    452                 icmp_attach(pData, m);
    453455                pData->icmp_socket.so_laddr.s_addr = ip->ip_src.s_addr; /* XXX: hack*/
    454456                pData->icmp_socket.so_icmp_id = icp->icmp_id;
    455457                pData->icmp_socket.so_icmp_seq = icp->icmp_seq;
    456                 m->m_so = &pData->icmp_socket;
    457458                memset(&ipopt, 0, sizeof(IP_OPTION_INFORMATION));
    458459                ipopt.Ttl = ip->ip_ttl;
    459460                status = ICMP_SEND_ECHO(pData->phEvents[VBOX_ICMP_EVENT_INDEX], notify_slirp, addr.sin_addr.s_addr,
    460461                                icp->icmp_data, icmplen - ICMP_MINLEN, &ipopt);
    461                 if (status == 0 && (error = GetLastError()) != ERROR_IO_PENDING)
     462                error = GetLastError();
     463                if (   status != 0
     464                    || error == ERROR_IO_PENDING)
    462465                {
    463                     error = GetLastError();
    464                     LogRel(("NAT: Error (%d) occurred while sending ICMP (", error));
    465                     switch (error)
    466                     {
    467                         case ERROR_INVALID_PARAMETER:
    468                             LogRel(("icmp_socket:%lx is invalid)\n", pData->icmp_socket.s));
    469                             break;
    470                         case ERROR_NOT_SUPPORTED:
    471                             LogRel(("operation is unsupported)\n"));
    472                             break;
    473                         case ERROR_NOT_ENOUGH_MEMORY:
    474                             LogRel(("OOM!!!)\n"));
    475                             break;
    476                         case IP_BUF_TOO_SMALL:
    477                             LogRel(("Buffer too small)\n"));
    478                             break;
    479                         default:
    480                             LogRel(("Other error!!!)\n"));
    481                             break;
    482                     }
     466                    icmp_attach(pData, m);
     467                    m->m_so = &pData->icmp_socket;
     468                    /* don't let m_freem at the end free atached buffer */
     469                    return;
     470                }
     471                LogRel(("NAT: Error (%d) occurred while sending ICMP (", error));
     472                switch (error)
     473                {
     474                    case ERROR_INVALID_PARAMETER:
     475                        LogRel(("icmp_socket:%lx is invalid)\n", pData->icmp_socket.s));
     476                        break;
     477                    case ERROR_NOT_SUPPORTED:
     478                        LogRel(("operation is unsupported)\n"));
     479                        break;
     480                    case ERROR_NOT_ENOUGH_MEMORY:
     481                        LogRel(("OOM!!!)\n"));
     482                        break;
     483                    case IP_BUF_TOO_SMALL:
     484                        LogRel(("Buffer too small)\n"));
     485                        break;
     486                    default:
     487                        LogRel(("Other error!!!)\n"));
     488                        break;
    483489                }
    484490#endif /* RT_OS_WINDOWS */
     
    486492            break;
    487493        case ICMP_UNREACH:
    488             /* XXX? report error? close socket? */
    489494        case ICMP_TIMXCEED:
     495            /* @todo(vvl): both up cases comes from guest,
     496             *  indeed right solution would be find the socket
     497             *  corresponding to ICMP data and close it. 
     498             */
    490499        case ICMP_PARAMPROB:
    491500        case ICMP_SOURCEQUENCH:
     
    494503        case ICMP_REDIRECT:
    495504            icmpstat.icps_notsupp++;
    496             m_freem(pData, m);
    497505            break;
    498506
    499507        default:
    500508            icmpstat.icps_badtype++;
    501             m_freem(pData, m);
    502509    } /* switch */
    503     if (m->m_next != NULL && icp != NULL)
     510   
     511end_error:
     512    m_freem(pData, m);
     513    if (   !fIcpOnMbuf
     514        && !icp)
    504515        RTMemFree(icp);
    505 
    506 end_error:
    507     /* m is m_free()'d xor put in a socket xor or given to ip_send */
    508     ;
    509516}
    510517
     
    684691/*
    685692 * Reflect the ip packet back to the source
     693 * Note: m isn't duplicated by this method and more delivered to ip_output then.
    686694 */
    687695void
Note: See TracChangeset for help on using the changeset viewer.

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