VirtualBox

Ignore:
Timestamp:
Jul 14, 2019 3:18:41 AM (5 years ago)
Author:
vboxsync
Message:

Main/DHCPServer,Dhcpd,VBoxManage: Added --log option to the DHCP server so we can start logging early. Added log rotation and limits. Put the config file next to the log and leases file. Validate DHCP options by reusing the parser code from the server, adding a bunch more DHCP options to the parser. Removed legacy and hardcoded configuration options from the dhcp server, it's all config file now. Fixed a bug in the option parsing of the VBoxManage dhcpserver add/modify commands. bugref:9288

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.cpp

    r79524 r79761  
    1616 */
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include "DhcpdInternal.h"
    1923#include "DhcpOptions.h"
    2024#include "DhcpMessage.h"
     25
     26#include <iprt/cidr.h>
    2127
    2228
     
    102108
    103109
     110int DhcpOption::parse1(bool &aValue, const char *pcszValue)
     111{
     112    pcszValue = RTStrStripL(pcszValue);
     113    if (   strcmp(pcszValue, "true") == 0
     114        || strcmp(pcszValue, "1")    == 0
     115        || strcmp(pcszValue, "yes")  == 0
     116        || strcmp(pcszValue, "on")   == 0 )
     117    {
     118        aValue = true;
     119        return VINF_SUCCESS;
     120    }
     121
     122    if (   strcmp(pcszValue, "false") == 0
     123        || strcmp(pcszValue, "0")     == 0
     124        || strcmp(pcszValue, "no")    == 0
     125        || strcmp(pcszValue, "off")   == 0 )
     126    {
     127        aValue = false;
     128        return VINF_SUCCESS;
     129    }
     130
     131    uint8_t bTmp;
     132    int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &bTmp);
     133    if (rc == VERR_TRAILING_SPACES)
     134        rc = VINF_SUCCESS;
     135    if (RT_SUCCESS(rc))
     136        aValue = bTmp != 0;
     137
     138    return rc;
     139}
     140
     141
    104142int DhcpOption::parse1(uint8_t &aValue, const char *pcszValue)
    105143{
    106144    int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &aValue);
    107 
    108145    if (rc == VERR_TRAILING_SPACES)
    109146        rc = VINF_SUCCESS;
     
    138175
    139176
    140 int DhcpOption::parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue)
    141 {
    142     std::vector<RTNETADDRIPV4> l;
    143     int rc;
     177int DhcpOption::parse1(DhcpIpv4AddrAndMask &aValue, const char *pcszValue)
     178{
     179    return RTCidrStrToIPv4(pcszValue, &aValue.Ipv4, &aValue.Mask);
     180}
     181
     182
     183template <typename a_Type>
     184static int DhcpOption::parseList(std::vector<a_Type> &aList, const char *pcszValue)
     185{
     186    std::vector<a_Type> vecTmp;
    144187
    145188    pcszValue = RTStrStripL(pcszValue);
    146     do {
    147         RTNETADDRIPV4 Addr;
    148         char *pszNext;
    149 
    150         rc = RTNetStrToIPv4AddrEx(pcszValue, &Addr, &pszNext);
    151         if (RT_FAILURE(rc))
     189    for (;;)
     190    {
     191        /* Assume space, tab, comma or semicolon is used as separator (superset of RTStrStrip): */
     192        const char *pszNext = strpbrk(pcszValue, " ,;:\t\n\r");
     193        char szTmp[256];
     194        if (pszNext)
     195        {
     196            size_t cchToCopy = pszNext - pcszValue;
     197            if (cchToCopy >= sizeof(szTmp))
     198                return VERR_INVALID_PARAMETER;
     199            memcpy(szTmp, pcszValue, cchToCopy);
     200            szTmp[cchToCopy] = '\0';
     201            pcszValue = szTmp;
     202
     203            /* Advance pszNext past the separator character and fluff: */
     204            char ch;
     205            do
     206                pszNext++;
     207            while ((ch = *pszNext) == ' ' || ch == ':' || ch == ';' || ch == '\t' || ch == '\n' || ch == '\r');
     208            if (ch == '\0')
     209                pszNext = NULL;
     210        }
     211
     212        /* Try convert it: */
     213        a_Type Value;
     214        int rc = DhcpOption::parse1(Value, pcszValue);
     215        if (RT_SUCCESS(rc))
     216            vecTmp.push_back(Value);
     217        else
    152218            return VERR_INVALID_PARAMETER;
    153219
    154         if (rc == VWRN_TRAILING_CHARS)
     220        if (pszNext)
     221            pcszValue = pszNext;
     222        else
     223            break;
     224    }
     225
     226    aList.swap(vecTmp);
     227    return VINF_SUCCESS;
     228
     229}
     230
     231/** ASSUME that uint8_t means hex byte strings. */
     232template <>
     233static int DhcpOption::parseList(std::vector<uint8_t> &aList, const char *pcszValue)
     234{
     235    uint8_t     abBuf[256];
     236    const char *pszNext = NULL;
     237    size_t      cbReturned = 0;
     238    int rc = RTStrConvertHexBytesEx(RTStrStripL(pcszValue), abBuf, sizeof(abBuf), RTSTRCONVERTHEXBYTES_F_SEP_COLON,
     239                                    &pszNext, &cbReturned);
     240    if (RT_SUCCESS(rc))
     241    {
     242        if (pszNext)
     243            pszNext = RTStrStripL(pszNext);
     244        if (*pszNext)
    155245        {
    156             pcszValue = RTStrStripL(pszNext);
    157             if (pcszValue == pszNext) /* garbage after address */
    158                 return VERR_INVALID_PARAMETER;
     246            for (size_t i = 0; i < cbReturned; i++)
     247                aList.push_back(abBuf[i]);
     248            return VINF_SUCCESS;
    159249        }
    160 
    161         l.push_back(Addr);
    162 
    163         /*
    164          * If we got VINF_SUCCESS or VWRN_TRAILING_SPACES then this
    165          * was the last address and we are done.
    166          */
    167     } while (rc == VWRN_TRAILING_CHARS);
    168 
    169     aList.swap(l);
    170     return VINF_SUCCESS;
    171 }
     250        rc = VERR_TRAILING_CHARS;
     251    }
     252    return rc;
     253}
     254
    172255
    173256
     
    208291
    209292
    210 DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue)
    211 {
     293DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc /*= NULL*/)
     294{
     295    int rcIgn;
     296    if (!prc)
     297        prc = &rcIgn;
     298
    212299    switch (aEnc)
    213300    {
    214     case 0: /* DhcpOptEncoding_Legacy */
    215         switch (aOptCode)
    216         {
    217 #define HANDLE(_OptClass)                               \
    218             case _OptClass::optcode:                    \
    219                 return _OptClass::parse(pcszValue);
    220 
    221         HANDLE(OptSubnetMask);
    222         HANDLE(OptRouter);
    223         HANDLE(OptDNS);
    224         HANDLE(OptHostName);
    225         HANDLE(OptDomainName);
    226         HANDLE(OptRootPath);
    227         HANDLE(OptLeaseTime);
    228         HANDLE(OptRenewalTime);
    229         HANDLE(OptRebindingTime);
     301        case 0: /* DhcpOptEncoding_Legacy */
     302            switch (aOptCode)
     303            {
     304#define HANDLE(a_OptClass)  \
     305                case a_OptClass::optcode: \
     306                    return a_OptClass::parse(pcszValue, prc)
     307
     308                HANDLE(OptSubnetMask);                  // 1
     309                HANDLE(OptTimeOffset);                  // 2
     310                HANDLE(OptRouters);                     // 3
     311                HANDLE(OptTimeServers);                 // 4
     312                HANDLE(OptNameServers);                 // 5
     313                HANDLE(OptDNSes);                       // 6
     314                HANDLE(OptLogServers);                  // 7
     315                HANDLE(OptCookieServers);               // 8
     316                HANDLE(OptLPRServers);                  // 9
     317                HANDLE(OptImpressServers);              // 10
     318                HANDLE(OptResourceLocationServers);     // 11
     319                HANDLE(OptHostName);                    // 12
     320                HANDLE(OptBootFileSize);                // 13
     321                HANDLE(OptMeritDumpFile);               // 14
     322                HANDLE(OptDomainName);                  // 15
     323                HANDLE(OptSwapServer);                  // 16
     324                HANDLE(OptRootPath);                    // 17
     325                HANDLE(OptExtensionPath);               // 18
     326                HANDLE(OptIPForwarding);                // 19
     327                HANDLE(OptNonLocalSourceRouting);       // 20
     328                HANDLE(OptPolicyFilter);                // 21
     329                HANDLE(OptMaxDatagramReassemblySize);   // 22
     330                HANDLE(OptDefaultIPTTL);                // 23
     331                HANDLE(OptDefaultPathMTUAgingTimeout);  // 24
     332                HANDLE(OptPathMTUPlateauTable);         // 25
     333                HANDLE(OptInterfaceMTU);                // 26
     334                HANDLE(OptAllSubnetsAreLocal);          // 27
     335                HANDLE(OptBroadcastAddress);            // 28
     336                HANDLE(OptPerformMaskDiscovery);        // 29
     337                HANDLE(OptMaskSupplier);                // 30
     338                HANDLE(OptPerformRouterDiscovery);      // 31
     339                HANDLE(OptRouterSolicitationAddress);   // 32
     340                HANDLE(OptStaticRoute);                 // 33
     341                HANDLE(OptTrailerEncapsulation);        // 34
     342                HANDLE(OptARPCacheTimeout);             // 35
     343                HANDLE(OptEthernetEncapsulation);       // 36
     344                HANDLE(OptTCPDefaultTTL);               // 37
     345                HANDLE(OptTCPKeepaliveInterval);        // 38
     346                HANDLE(OptTCPKeepaliveGarbage);         // 39
     347                HANDLE(OptNISDomain);                   // 40
     348                HANDLE(OptNISServers);                  // 41
     349                HANDLE(OptNTPServers);                  // 42
     350                HANDLE(OptVendorSpecificInfo);          // 43
     351                HANDLE(OptNetBIOSNameServers);          // 44
     352                HANDLE(OptNetBIOSDatagramServers);      // 45
     353                HANDLE(OptNetBIOSNodeType);             // 46
     354                HANDLE(OptNetBIOSScope);                // 47
     355                HANDLE(OptXWindowsFontServers);         // 48
     356                HANDLE(OptXWindowsDisplayManager);      // 49
     357#ifndef IN_VBOXSVC /* Don't allow these in new configs */
     358                // OptRequestedAddress (50) is client only and not configurable.
     359                HANDLE(OptLeaseTime);                   // 51 - for historical reasons?  Configuable elsewhere now.
     360                // OptOptionOverload (52) is part of the protocol and not configurable.
     361                // OptMessageType (53) is part of the protocol and not configurable.
     362                // OptServerId (54) is the IP address of the server and configurable elsewhere.
     363                // OptParameterRequest (55) is client only and not configurable.
     364                // OptMessage (56) is server failure message and not configurable.
     365                // OptMaxDHCPMessageSize (57) is client only (?) and not configurable.
     366                HANDLE(OptRenewalTime);                 // 58 - for historical reasons?
     367                HANDLE(OptRebindingTime);               // 59 - for historical reasons?
     368                // OptVendorClassId (60) is client only and not configurable.
     369                // OptClientId (61) is client only and not configurable.
     370#endif
     371                HANDLE(OptNetWareIPDomainName);         // 62
     372                HANDLE(OptNetWareIPInformation);        // 63
     373                HANDLE(OptNISPlusDomain);               // 64
     374                HANDLE(OptNISPlusServers);              // 65
     375                HANDLE(OptTFTPServer);                  // 66 - perhaps we should use an alternative way to configure these.
     376                HANDLE(OptBootFileName);                // 67 - perhaps we should use an alternative way to configure these.
     377                HANDLE(OptMobileIPHomeAgents);          // 68
     378                HANDLE(OptSMTPServers);                 // 69
     379                HANDLE(OptPOP3Servers);                 // 70
     380                HANDLE(OptNNTPServers);                 // 71
     381                HANDLE(OptWWWServers);                  // 72
     382                HANDLE(OptFingerServers);               // 73
     383                HANDLE(OptIRCServers);                  // 74
     384                HANDLE(OptStreetTalkServers);           // 75
     385                HANDLE(OptSTDAServers);                 // 76
     386                // OptUserClassId (77) is client only and not configurable.
     387                HANDLE(OptSLPDirectoryAgent);           // 78
     388                HANDLE(OptSLPServiceScope);             // 79
     389                // OptRapidCommit (80) is not configurable.
    230390
    231391#undef HANDLE
     392                default:
     393                    if (prc)
     394                        *prc = VERR_NOT_IMPLEMENTED;
     395                    return NULL;
     396            }
     397            break;
     398
     399        case 1:
     400            return RawOption::parse(aOptCode, pcszValue, prc);
     401
    232402        default:
     403            if (prc)
     404                *prc = VERR_WRONG_TYPE;
    233405            return NULL;
    234         }
    235         break;
    236 
    237     case 1:
    238         return RawOption::parse(aOptCode, pcszValue);
    239 
    240     default:
    241         return NULL;
    242     }
    243 }
     406    }
     407}
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