Exemplo n.º 1
0
/* XXX: Having fIPv6 we might emprove adress verification comparing address length 
 * with INET[6]_ADDRLEN
 */
int netPfStrToPf(const char *pcszStrPortForward, int fIPv6, PPORTFORWARDRULE pPfr)
{
    char *pszName;
    int  proto;
    char *pszHostAddr;
    char *pszGuestAddr;
    uint16_t u16HostPort;
    uint16_t u16GuestPort;
    bool fTcpProto = false;

    char *pszRawBegin = NULL; 
    char *pszRaw = NULL;
    int idxRaw = 0;
    int cbToken = 0;
    int cbRaw = 0;
    int rc = VINF_SUCCESS;

    AssertPtrReturn(pcszStrPortForward, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pPfr, VERR_INVALID_PARAMETER);

    memset(pPfr, 0, sizeof(PORTFORWARDRULE));

    pszHostAddr = &pPfr->aszPfrHostAddr[0];
    pszGuestAddr = &pPfr->aszPfrGuestAddr[0];
    pszName = &pPfr->aszPfrName[0];

    cbRaw = strlen(pcszStrPortForward); 

    /* Minimal rule ":tcp:[]:0:[]:0" has got lenght 14 */
    AssertReturn(cbRaw > 14, VERR_INVALID_PARAMETER);
    
    pszRaw = RTStrDup(pcszStrPortForward);

    AssertPtrReturn(pszRaw, VERR_NO_MEMORY);

    pszRawBegin = pszRaw;

    /* name */
    if (pszRaw[idxRaw] == PF_FIELD_SEPARATOR) 
        idxRaw = 1; /* begin of the next segment */
    else
    {
        char *pszEndOfName = RTStrStr(pszRaw + 1, PF_STR_FIELD_SEPARATOR);
        if (!pszEndOfName)
            goto invalid_parameter;

        cbToken = (pszEndOfName) - pszRaw; /* don't take : into account */
        /* XXX it's unacceptable to have only name entry in PF */
        AssertReturn(cbToken < cbRaw, VERR_INVALID_PARAMETER);
        
        if (   cbToken < 0
            || (size_t)cbToken >= PF_NAMELEN)
            goto invalid_parameter;

        RTStrCopy(pszName, 
                  RT_MIN((size_t)cbToken + 1, PF_NAMELEN), 
                  pszRaw);
        pszRaw += cbToken; /* move to separator */
    }
    
    AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, VERR_INVALID_PARAMETER);
    /* protocol */

    pszRaw++; /* skip separator */
    idxRaw = 0;
    
    cbRaw--;

    if (     ((    fTcpProto = (RTStrNICmp(pszRaw, "tcp", 3) == 0)
              ||  (RTStrNICmp(pszRaw, "udp", 3) == 0))
          && (pszRaw[3] == PF_FIELD_SEPARATOR)))
    {
        proto = (fTcpProto ? IPPROTO_TCP : IPPROTO_UDP);
        idxRaw = 3;
    }
    else
        goto invalid_parameter;
                    
    pszRaw += idxRaw;
    cbRaw -= idxRaw;
    idxRaw = 0;
                    
    idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw, 
                                         pszHostAddr, INET6_ADDRSTRLEN,
                                         true, &u16HostPort);
    if (idxRaw < 0)
        return VERR_INVALID_PARAMETER;

    pszRaw += idxRaw;
    cbRaw -= idxRaw;

    Assert(pszRaw[0] == PF_FIELD_SEPARATOR);

    idxRaw = 0;

    idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw, 
                                          pszGuestAddr, 
                                          INET6_ADDRSTRLEN,
                                          false,
                                          &u16GuestPort);

    if (idxRaw < 0)
        goto invalid_parameter;

    /* XXX: fill the rule */
    pPfr->fPfrIPv6 = fIPv6;
    pPfr->iPfrProto = proto;

    
    if (strlen(pszHostAddr))
    {
        if (!fIPv6)
            rc = RTNetStrToIPv4Addr(pszHostAddr, &pPfr->uPfrHostAddr.IPv4);
#if 0 /* No IPv6 yet */
        else
            rc = RTNetStrToIPv6Addr(pszHostAddr, &pPfr->uPfrHostAddr.IPv6);
#endif

        if (RT_FAILURE(rc))
            goto invalid_parameter;
    }
    
    pPfr->u16PfrHostPort = u16HostPort;

    if (strlen(pszGuestAddr))
    {
        if (!fIPv6)
            rc = RTNetStrToIPv4Addr(pszGuestAddr, &pPfr->uPfrGuestAddr.IPv4);       
#if 0
        else
            rc = RTNetStrToIPv6Addr(pszGuestAddr, &pPfr->uPfrGuestAddr.IPv6);
#endif
        if (RT_FAILURE(rc))
            goto invalid_parameter;
    }
    else
        goto invalid_parameter; /* guest address should be defined */
    
    pPfr->u16PfrGuestPort = u16GuestPort;
    
    Log(("name: %s\n"
         "proto: %d\n"
         "host address: %s\n"
         "host port: %d\n"
         "guest address: %s\n"
         "guest port:%d\n",
         pszName, proto,
         pszHostAddr, u16HostPort,
         pszGuestAddr, u16GuestPort));

    RTStrFree(pszRawBegin);
    return VINF_SUCCESS;
    
invalid_parameter:
    RTStrFree(pszRawBegin);
    if (pPfr)
        memset(pPfr, 0, sizeof(PORTFORWARDRULE));
    return VERR_INVALID_PARAMETER;
}
HRESULT HostNetworkInterface::enableStaticIPConfigV6(const com::Utf8Str &aIPV6Address,
                                                     ULONG aIPV6NetworkMaskPrefixLength)
{
#ifndef VBOX_WITH_HOSTNETIF_API
    return E_NOTIMPL;
#else
    if (aIPV6NetworkMaskPrefixLength > 128)
        return mVirtualBox->setErrorBoth(E_INVALIDARG, VERR_INVALID_PARAMETER,
                   "Invalid IPv6 prefix length");

    int rc;

    RTNETADDRIPV6 AddrOld, AddrNew;
    char *pszZoneIgnored;
    bool fAddrChanged;

    rc = RTNetStrToIPv6Addr(aIPV6Address.c_str(), &AddrNew, &pszZoneIgnored);
    if (RT_FAILURE(rc))
    {
        return mVirtualBox->setErrorBoth(E_INVALIDARG, rc, "Invalid IPv6 address");
    }

    rc = RTNetStrToIPv6Addr(com::Utf8Str(m.realIPV6Address).c_str(), &AddrOld, &pszZoneIgnored);
    if (RT_SUCCESS(rc))
    {
        fAddrChanged = (AddrNew.s.Lo != AddrOld.s.Lo || AddrNew.s.Hi != AddrOld.s.Hi);
    }
    else
    {
        fAddrChanged = true;
    }

    if (   fAddrChanged
        || m.realIPV6PrefixLength != aIPV6NetworkMaskPrefixLength)
    {
        if (aIPV6NetworkMaskPrefixLength == 0)
            aIPV6NetworkMaskPrefixLength = 64;
        rc = NetIfEnableStaticIpConfigV6(mVirtualBox, this, m.IPV6Address.c_str(),
                                         aIPV6Address.c_str(),
                                         aIPV6NetworkMaskPrefixLength);
        if (RT_FAILURE(rc))
        {
            LogRel(("Failed to EnableStaticIpConfigV6 with rc=%Rrc\n", rc));
            return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
        }
        else
        {
            m.realIPV6Address = aIPV6Address;
            m.realIPV6PrefixLength = aIPV6NetworkMaskPrefixLength;
#if defined(RT_OS_WINDOWS)
            saveAdapterConfigIPv6(Bstr(aIPV6Address).raw(), aIPV6NetworkMaskPrefixLength);
#else /* !defined(RT_OS_WINDOWS) */
            if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPV6Address",
                                                         mInterfaceName.c_str()).raw(),
                                                 Bstr(aIPV6Address).raw())))
                return E_FAIL;
            if (FAILED(mVirtualBox->SetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask",
                                                         mInterfaceName.c_str()).raw(),
                                                 BstrFmt("%u", aIPV6NetworkMaskPrefixLength).raw())))
#endif /* !defined(RT_OS_WINDOWS) */
                return E_FAIL;
        }

    }
    return S_OK;
#endif
}