Beispiel #1
0
/**
 * @note This function will free m!
 */
int udp_output(PNATState pData, struct socket *so, struct mbuf *m,
               struct sockaddr_in *addr)
{
    struct sockaddr_in saddr, daddr;
#ifdef VBOX_WITH_NAT_UDP_SOCKET_CLONE
    struct socket *pSocketClone = NULL;
#endif
    Assert(so->so_type == IPPROTO_UDP);
    LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4\n",
                 so, (long)m, addr->sin_addr.s_addr));

    saddr = *addr;
    if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
    {
        saddr.sin_addr.s_addr = so->so_faddr.s_addr;
        if (slirpIsWideCasting(pData, so->so_faddr.s_addr))
        {
            /**
             * We haven't got real firewall but have got its submodule libalias.
             */
            m->m_flags |= M_SKIP_FIREWALL;
            /**
             * udp/137 port is Name Service in NetBIOS protocol. for some reasons Windows guest rejects
             * accept data from non-aliased server.
             */
            if (   (so->so_fport == so->so_lport)
                && (so->so_fport == RT_H2N_U16(137)))
                saddr.sin_addr.s_addr = alias_addr.s_addr;
            else
                saddr.sin_addr.s_addr = addr->sin_addr.s_addr;
            /* we shouldn't override initial socket */
#ifdef VBOX_WITH_NAT_UDP_SOCKET_CLONE
            if (so->so_cCloneCounter)
                pSocketClone = soLookUpClonedUDPSocket(pData, so, addr->sin_addr.s_addr);
            if (!pSocketClone)
                pSocketClone = soCloneUDPSocketWithForegnAddr(pData, false, so, addr->sin_addr.s_addr);
            Assert((pSocketClone));
            so = pSocketClone;
#else
            so->so_faddr.s_addr = addr->sin_addr.s_addr;
#endif
        }
    }

    /* Any UDP packet to the loopback address must be translated to be from
     * the forwarding address, i.e. 10.0.2.2. */
    if (   (saddr.sin_addr.s_addr & RT_H2N_U32_C(IN_CLASSA_NET))
        == RT_H2N_U32_C(INADDR_LOOPBACK & IN_CLASSA_NET))
        saddr.sin_addr.s_addr = alias_addr.s_addr;

    daddr.sin_addr = so->so_laddr;
    daddr.sin_port = so->so_lport;

    return udp_output2(pData, so, m, &saddr, &daddr, so->so_iptos);
}
DECLINLINE(bool) slirpSend2Home(PNATState pData, struct socket *pSo, const void *pvBuf, uint32_t cbBuf, int iFlags)
{
    int idxAddr;
    int ret = 0;
    bool fSendDone = false;
    LogFlowFunc(("Enter pSo:%R[natsock] pvBuf: %p, cbBuf: %d, iFlags: %d\n", pSo, pvBuf, cbBuf, iFlags));
    for (idxAddr = 0; idxAddr < pData->cInHomeAddressSize; ++idxAddr)
    {

        struct socket *pNewSocket = soCloneUDPSocketWithForegnAddr(pData, pSo, pData->pInSockAddrHomeAddress[idxAddr].sin_addr);
        AssertReturn((pNewSocket, false));
        pData->pInSockAddrHomeAddress[idxAddr].sin_port = pSo->so_fport;
        /** @todo more verbose on errors,
         * @note: we shouldn't care if this send fail or not (we're in broadcast).
         */
        LogFunc(("send %d bytes to %RTnaipv4 from %R[natsock]\n", cbBuf, pData->pInSockAddrHomeAddress[idxAddr].sin_addr.s_addr, pNewSocket));
        ret = sendto(pNewSocket->s, pvBuf, cbBuf, iFlags, (struct sockaddr *)&pData->pInSockAddrHomeAddress[idxAddr], sizeof(struct sockaddr_in));
        if (ret < 0)
            LogFunc(("Failed to send %d bytes to %RTnaipv4\n", cbBuf, pData->pInSockAddrHomeAddress[idxAddr].sin_addr.s_addr));
        fSendDone |= ret > 0;
    }
    LogFlowFunc(("Leave %RTbool\n", fSendDone));
    return fSendDone;
}