/**
 * @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;

    Assert(so->so_type == IPPROTO_UDP);
    LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4\n", so, m, addr->sin_addr.s_addr));

    if (so->so_laddr.s_addr == INADDR_ANY)
    {
        if (pData->guest_addr_guess.s_addr != INADDR_ANY)
        {
            LogRel2(("NAT: port-forward: using %RTnaipv4 for %R[natsock]\n",
                     pData->guest_addr_guess.s_addr, so));
            so->so_laddr = pData->guest_addr_guess;
        }
        else
        {
            LogRel2(("NAT: port-forward: guest address unknown for %R[natsock]\n", so));
            m_freem(pData, m);
            return 0;
        }
    }

    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;
            so->so_faddr.s_addr = addr->sin_addr.s_addr;
        }
    }

    /* 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);
}
Beispiel #2
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);
}