/* 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 }