VirtualBox

Changeset 87363 in vbox


Ignore:
Timestamp:
Jan 22, 2021 12:48:31 AM (4 years ago)
Author:
vboxsync
Message:

Main/NATNetwork: NATNetwork::setNetwork - if there are IPv4 port
forwarding rules do best-effort attempt at covnerting them to the new
prefix. Leave untouched any rules that have destination not on the
old network, and rules where the destination does not fit into the new
network when the new network is smaller than the old one. bugref:9909.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/NATNetworkImpl.cpp

    r87360 r87363  
    2424#include <iprt/asm.h>
    2525#include <iprt/cpp/utils.h>
     26#include <iprt/net.h>
    2627#include <iprt/cidr.h>
    2728#include <iprt/net.h>
     
    7475    uint32_t offGateway;
    7576    uint32_t offDhcp;
     77
     78    void recalculatePortForwarding(const RTNETADDRIPV4 &AddrNew, const RTNETADDRIPV4 &MaskNew);
    7679};
    7780
     
    261264HRESULT NATNetwork::setNetwork(const com::Utf8Str &aIPv4NetworkCidr)
    262265{
    263     RTNETADDRIPV4 Addr, Mask;
     266    RTNETADDRIPV4 Net, Mask;
    264267    int iPrefix;
    265268    int rc;
    266269
    267     rc = RTNetStrToIPv4Cidr(aIPv4NetworkCidr.c_str(), &Addr, &iPrefix);
     270    rc = RTNetStrToIPv4Cidr(aIPv4NetworkCidr.c_str(), &Net, &iPrefix);
    268271    if (RT_FAILURE(rc))
    269272        return setError(E_FAIL, "%s is not a valid IPv4 CIDR notation",
     
    284287        aIPv4NetworkCidr.c_str(), iPrefix, rc));
    285288
    286     if ((Addr.u & ~Mask.u) != 0)
     289    if ((Net.u & ~Mask.u) != 0)
    287290        return setError(E_FAIL,
    288291            "%s: the specified address is longer than the specified prefix",
     
    290293
    291294    /* normalized CIDR notation */
    292     com::Utf8StrFmt strCidr("%RTnaipv4/%d", Addr.u, iPrefix);
     295    com::Utf8StrFmt strCidr("%RTnaipv4/%d", Net.u, iPrefix);
    293296
    294297    {
     
    298301            return S_OK;
    299302
    300         /**
    301          * @todo
    302          * silently ignore network cidr update for now.
    303          * todo: keep internally guest address of port forward rule
    304          * as offset from network id.
    305          */
    306         if (!m->s.mapPortForwardRules4.empty())
    307             return S_OK;
    308 
     303        m->recalculatePortForwarding(Net, Mask);
    309304
    310305        m->s.strIPv4NetworkCidr = strCidr;
     
    316311    ComAssertComRCRetRC(hrc);
    317312    return S_OK;
     313}
     314
     315
     316/**
     317 * Do best effort attempt at converting existing port forwarding rules
     318 * from the old prefix to the new one.  This might not be possible if
     319 * the new prefix is longer (i.e. the network is smaller) or if a rule
     320 * lists destination not from the network (though that rule wouldn't
     321 * be terribly useful, at least currently).
     322 */
     323void NATNetwork::Data::recalculatePortForwarding(const RTNETADDRIPV4 &NetNew,
     324                                                 const RTNETADDRIPV4 &MaskNew)
     325{
     326    RTNETADDRIPV4 NetOld, MaskOld;
     327    int iPrefixOld;
     328    int rc;
     329
     330    if (s.mapPortForwardRules4.empty())
     331        return;                 /* nothing to do */
     332
     333    rc = RTNetStrToIPv4Cidr(s.strIPv4NetworkCidr.c_str(), &NetOld, &iPrefixOld);
     334    if (RT_FAILURE(rc))
     335        return;
     336
     337    rc = RTNetPrefixToMaskIPv4(iPrefixOld, &MaskOld);
     338    if (RT_FAILURE(rc))
     339        return;
     340
     341    for (settings::NATRulesMap::iterator it = s.mapPortForwardRules4.begin();
     342         it != s.mapPortForwardRules4.end();
     343         ++it)
     344    {
     345        settings::NATRule &rule = it->second;
     346
     347        /* parse the old destination address */
     348        RTNETADDRIPV4 AddrOld;
     349        rc = RTNetStrToIPv4Addr(rule.strGuestIP.c_str(), &AddrOld);
     350        if (RT_FAILURE(rc))
     351            continue;
     352
     353        /* is it in the old network? (likely) */
     354        if ((AddrOld.u & MaskOld.u) != NetOld.u)
     355            continue;
     356
     357        uint32_t u32Host = (AddrOld.u & ~MaskOld.u);
     358
     359        /* does it fit into the new network? */
     360        if ((u32Host & MaskNew.u) != 0)
     361            continue;
     362
     363        rule.strGuestIP.printf("%RTnaipv4", NetNew.u | u32Host);
     364    }
    318365}
    319366
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