VirtualBox

Changeset 68056 in vbox


Ignore:
Timestamp:
Jul 20, 2017 9:47:06 AM (7 years ago)
Author:
vboxsync
Message:

AdpCtl: (bugref:8866) Guess missing netmask and bring interface up

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp

    r67757 r68056  
    3333#include <fcntl.h>
    3434#ifdef RT_OS_LINUX
     35# include <arpa/inet.h>
    3536# include <net/if.h>
    3637# include <linux/types.h>
     
    254255
    255256
     257#ifdef RT_OS_LINUX
     258/*
     259 * Helper class to incapsulate IPv4 address conversion.
     260 */
     261class AddressIPv4
     262{
     263public:
     264    AddressIPv4(const char *pcszAddress, const char *pcszNetmask = 0)
     265        {
     266            if (pcszNetmask)
     267                m_Prefix = maskToPrefix(pcszNetmask);
     268            else
     269            {
     270                /*
     271                 * Since guessing network mask is probably futile we simply use 24,
     272                 * as it matches our defaults. When non-default values are used
     273                 * providing a proper netmask is up to the user.
     274                 */
     275                m_Prefix = 24;
     276            }
     277            inet_pton(AF_INET, pcszAddress, &(m_Address.sin_addr));
     278            snprintf(m_szAddressAndMask, sizeof(m_szAddressAndMask), "%s/%d", pcszAddress, m_Prefix);
     279            m_Broadcast.sin_addr.s_addr = computeBroadcast(m_Address.sin_addr.s_addr, m_Prefix);
     280            inet_ntop(AF_INET, &(m_Broadcast.sin_addr), m_szBroadcast, sizeof(m_szBroadcast));
     281        }
     282    const char *getBroadcast() const { return m_szBroadcast; };
     283    const char *getAddressAndMask() const { return m_szAddressAndMask; };
     284private:
     285    unsigned int maskToPrefix(const char *pcszNetmask);
     286    unsigned long computeBroadcast(unsigned long ulAddress, unsigned int uPrefix);
     287
     288    unsigned int       m_Prefix;
     289    struct sockaddr_in m_Address;
     290    struct sockaddr_in m_Broadcast;
     291    char m_szAddressAndMask[INET_ADDRSTRLEN + 3]; /* e.g. 192.168.56.101/24 */
     292    char m_szBroadcast[INET_ADDRSTRLEN];
     293};
     294
     295unsigned int AddressIPv4::maskToPrefix(const char *pcszNetmask)
     296{
     297    unsigned cBits = 0;
     298    unsigned m[4];
     299
     300    if (sscanf(pcszNetmask, "%u.%u.%u.%u", &m[0], &m[1], &m[2], &m[3]) == 4)
     301    {
     302        for (int i = 0; i < 4 && m[i]; ++i)
     303        {
     304            int mask = m[i];
     305            while (mask & 0x80)
     306            {
     307                cBits++;
     308                mask <<= 1;
     309            }
     310        }
     311    }
     312    return cBits;
     313}
     314
     315unsigned long AddressIPv4::computeBroadcast(unsigned long ulAddress, unsigned int uPrefix)
     316{
     317    /* Note: the address is big-endian. */
     318    unsigned long ulNetworkMask = (1l << uPrefix) - 1;
     319    return (ulAddress & ulNetworkMask) | ~ulNetworkMask;
     320}
     321
     322
    256323/*
    257324 * Linux-specific implementation of 'ip' command, as other platforms do not support it.
     
    260327{
    261328public:
    262     CmdIpLinux() { pszBuffer = 0; m_pszPath = "/sbin/ip"; };
    263     virtual ~CmdIpLinux() { delete pszBuffer; };
     329    CmdIpLinux() { m_pszPath = "/sbin/ip"; };
    264330    /**
    265331     * IPv4 and IPv6 syntax is the same, so we override `remove` instead of implementing
     
    273339    virtual int addV4(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
    274340        {
    275             return execute(CmdList("addr") << "add" << combine(pcszAddress, pcszNetmask) <<
    276                            "dev" << pcszAdapter);
     341            AddressIPv4 addr(pcszAddress, pcszNetmask);
     342            bringUp(pcszAdapter);
     343            return execute(CmdList("addr") << "add" << addr.getAddressAndMask() <<
     344                           "broadcast" << addr.getBroadcast() << "dev" << pcszAdapter);
    277345        };
    278346    virtual int addV6(const char *pcszAdapter, const char *pcszAddress, const char *pcszNetmask = 0)
    279347        {
     348            bringUp(pcszAdapter);
    280349            return execute(CmdList("addr") << "add" << pcszAddress << "dev" << pcszAdapter);
    281350            NOREF(pcszNetmask);
     
    296365        { return CmdList("addr") << "show" << "dev" << pcszAdapter; };
    297366private:
    298     /** Converts address and network mask into a single string in CIDR notation (like 192.168.1.1/24) */
    299     const char *combine(const char *pcszAddress, const char *pcszNetmask);
    300 
    301     char *pszBuffer;
    302 };
    303 
    304 const char * CmdIpLinux::combine(const char *pcszAddress, const char *pcszNetmask)
    305 {
    306     delete pszBuffer;
    307     if (pcszNetmask)
    308     {
    309         unsigned cBits = 0;
    310         unsigned m[4];
    311         if (sscanf(pcszNetmask, "%u.%u.%u.%u", &m[0], &m[1], &m[2], &m[3]) == 4)
    312         {
    313             for (int i = 0; i < 4 && m[i]; ++i)
    314             {
    315                 int mask = m[i];
    316                 while (mask & 0x80)
    317                 {
    318                     cBits++;
    319                     mask <<= 1;
    320                 }
    321             }
    322             const size_t cbBuf = strlen(pcszAddress) + 4;
    323             pszBuffer = new char[cbBuf]; // '/xx\0'
    324             snprintf(pszBuffer, cbBuf, "%s/%u", pcszAddress, cBits);
    325             return pszBuffer;
    326         }
    327     }
    328     return pcszAddress;
    329 }
    330 
     367    /** Brings up the adapter */
     368    void bringUp(const char *pcszAdapter)
     369        { execute(CmdList("link") << "set" << "dev" << pcszAdapter << "up"); };
     370};
     371#endif /* RT_OS_LINUX */
    331372
    332373
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