VirtualBox

Changeset 79810 in vbox for trunk


Ignore:
Timestamp:
Jul 16, 2019 2:05:45 PM (6 years ago)
Author:
vboxsync
Message:

Dhcpd: Group conditions. bugref:9288

Location:
trunk/src/VBox/NetworkServices/Dhcpd
Files:
3 edited

Legend:

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

    r79800 r79810  
    6565        va_list va;
    6666        va_start(va, a_pszMsgFmt);
    67         m_strMsg.appendPrintf(a_pszMsgFmt, va);
     67        m_strMsg.appendPrintfV(a_pszMsgFmt, va);
    6868        va_end(va);
    6969    }
     
    9191            m_strMsg.append('/');
    9292            m_strMsg.append(pNode->getName());
    93             if (pNode->isElement())
     93            if (pNode->isElement() && pNode->getParent())
    9494            {
    9595                xml::ElementNode const *pElm = (xml::ElementNode const *)pNode;
    96                 for (xml::Node const *pNodeChild = pElm->getFirstChild(); pNodeChild != NULL;
    97                     pNodeChild = pNodeChild->getNextSibiling())
    98                     if (pNodeChild->isAttribute())
     96                for (xml::Node const *pAttrib = pElm->getFirstAttribute(); pAttrib != NULL;
     97                      pAttrib = pAttrib->getNextSibiling())
     98                    if (pAttrib->isAttribute())
    9999                    {
    100100                        m_strMsg.append("[@");
    101                         m_strMsg.append(pNodeChild->getName());
     101                        m_strMsg.append(pAttrib->getName());
    102102                        m_strMsg.append('=');
    103                         m_strMsg.append(pNodeChild->getValue());
     103                        m_strMsg.append(pAttrib->getValue());
    104104                        m_strMsg.append(']');
    105105                    }
     
    882882void GroupConfig::i_parseChild(const xml::ElementNode *pElmChild, bool fStrict)
    883883{
     884    /*
     885     * Match the condition
     886     */
     887    std::unique_ptr<GroupCondition> ptrCondition;
    884888    if (pElmChild->nameEquals("ConditionMAC"))
    885     { }
     889        ptrCondition.reset(new GroupConditionMAC());
    886890    else if (pElmChild->nameEquals("ConditionMACWildcard"))
    887     { }
     891        ptrCondition.reset(new GroupConditionMACWildcard());
    888892    else if (pElmChild->nameEquals("ConditionVendorClassID"))
    889     { }
     893        ptrCondition.reset(new GroupConditionVendorClassID());
    890894    else if (pElmChild->nameEquals("ConditionVendorClassIDWildcard"))
    891     { }
     895        ptrCondition.reset(new GroupConditionVendorClassIDWildcard());
    892896    else if (pElmChild->nameEquals("ConditionUserClassID"))
    893     { }
     897        ptrCondition.reset(new GroupConditionUserClassID());
    894898    else if (pElmChild->nameEquals("ConditionUserClassIDWildcard"))
    895     { }
     899        ptrCondition.reset(new GroupConditionUserClassIDWildcard());
    896900    else
    897901    {
     902        /*
     903         * Not a condition, pass it on to the base class.
     904         */
    898905        ConfigLevelBase::i_parseChild(pElmChild, fStrict);
    899906        return;
     907    }
     908
     909    /*
     910     * Get the attributes and initialize the condition.
     911     */
     912    bool fInclusive;
     913    if (!pElmChild->getAttributeValue("inclusive", fInclusive))
     914        fInclusive = true;
     915    const char *pszValue = pElmChild->findAttributeValue("value");
     916    if (pszValue && *pszValue)
     917    {
     918        int rc = ptrCondition->initCondition(pszValue, fInclusive);
     919        if (RT_SUCCESS(rc))
     920        {
     921            /*
     922             * Add it to the appropriate vector.
     923             */
     924            if (fInclusive)
     925                m_Inclusive.push_back(ptrCondition.release());
     926            else
     927                m_Exclusive.push_back(ptrCondition.release());
     928        }
     929        else
     930        {
     931            ConfigFileError Xcpt(pElmChild, "initCondition failed with %Rrc for '%s' and %RTbool", rc, pszValue, fInclusive);
     932            if (!fStrict)
     933                LogRelFunc(("%s, ignoring condition\n", Xcpt.what()));
     934            else
     935                throw ConfigFileError(Xcpt);
     936        }
     937    }
     938    else
     939    {
     940        ConfigFileError Xcpt(pElmChild, "condition value is empty or missing (inclusive=%RTbool)", fInclusive);
     941        if (!fStrict)
     942            LogRelFunc(("%s, ignoring condition\n", Xcpt.what()));
     943        else
     944            throw Xcpt;
    900945    }
    901946}
     
    9901035
    9911036    /* Groups: */
    992     RT_NOREF(a_ridVendorClass, a_ridUserClass); /* not yet */
     1037    for (GroupConfigMap::const_iterator itGrp = m_GroupConfigs.begin(); itGrp != m_GroupConfigs.end(); ++itGrp)
     1038        if (itGrp->second->match(a_ridClient, a_ridVendorClass, a_ridUserClass))
     1039            a_rRetConfigs.push_back(itGrp->second);
    9931040
    9941041    /* Global: */
     
    10761123    return a_rRetOpts;
    10771124}
     1125
     1126
     1127
     1128/*********************************************************************************************************************************
     1129*   Group Condition Matching                                                                                                     *
     1130*********************************************************************************************************************************/
     1131
     1132bool GroupConfig::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1133                        const OptUserClassId &a_ridUserClass) const
     1134{
     1135    /*
     1136     * Check the inclusive ones first, only one need to match.
     1137     */
     1138    for (GroupConditionVec::const_iterator itIncl = m_Inclusive.begin(); itIncl != m_Inclusive.end(); ++itIncl)
     1139        if ((*itIncl)->match(a_ridClient, a_ridVendorClass, a_ridUserClass))
     1140        {
     1141            /*
     1142             * Now make sure it isn't excluded by any of the exclusion condition.
     1143             */
     1144            for (GroupConditionVec::const_iterator itExcl = m_Exclusive.begin(); itExcl != m_Exclusive.end(); ++itExcl)
     1145                if ((*itIncl)->match(a_ridClient, a_ridVendorClass, a_ridUserClass))
     1146                    return false;
     1147            return true;
     1148        }
     1149
     1150    return false;
     1151}
     1152
     1153
     1154int GroupCondition::initCondition(const char *a_pszValue, bool a_fInclusive)
     1155{
     1156    m_fInclusive = a_fInclusive;
     1157    return m_strValue.assignNoThrow(a_pszValue);
     1158}
     1159
     1160
     1161bool GroupCondition::matchClassId(bool a_fPresent, const std::vector<uint8_t> &a_rBytes, bool fWildcard) const RT_NOEXCEPT
     1162{
     1163    if (a_fPresent)
     1164    {
     1165        size_t const cbBytes = a_rBytes.size();
     1166        if (cbBytes > 0)
     1167        {
     1168            if (a_rBytes[cbBytes - 1] == '\0')
     1169            {
     1170                uint8_t const *pb = &a_rBytes.front();
     1171                if (!fWildcard)
     1172                    return m_strValue.equals((const char *)pb);
     1173                return RTStrSimplePatternMatch(m_strValue.c_str(), (const char *)pb);
     1174            }
     1175
     1176            if (cbBytes <= 255)
     1177            {
     1178                char szTmp[256];
     1179                memcpy(szTmp, &a_rBytes.front(), cbBytes);
     1180                szTmp[cbBytes] = '\0';
     1181                if (!fWildcard)
     1182                    return m_strValue.equals(szTmp);
     1183                return RTStrSimplePatternMatch(m_strValue.c_str(), szTmp);
     1184            }
     1185        }
     1186    }
     1187    return false;
     1188
     1189}
     1190
     1191
     1192int GroupConditionMAC::initCondition(const char *a_pszValue, bool a_fInclusive)
     1193{
     1194    int vrc = RTNetStrToMacAddr(a_pszValue, &m_MACAddress);
     1195    if (RT_SUCCESS(vrc))
     1196        return GroupCondition::initCondition(a_pszValue, a_fInclusive);
     1197    return vrc;
     1198}
     1199
     1200
     1201bool GroupConditionMAC::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1202                              const OptUserClassId &a_ridUserClass) const
     1203{
     1204    RT_NOREF(a_ridVendorClass, a_ridUserClass);
     1205    return a_ridClient.mac() == m_MACAddress;
     1206}
     1207
     1208
     1209bool GroupConditionMACWildcard::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1210                                      const OptUserClassId &a_ridUserClass) const
     1211{
     1212    RT_NOREF(a_ridVendorClass, a_ridUserClass);
     1213    char szTmp[32];
     1214    RTStrPrintf(szTmp, sizeof(szTmp), "%RTmac", &a_ridClient.mac());
     1215    return RTStrSimplePatternMatch(m_strValue.c_str(), szTmp);
     1216}
     1217
     1218
     1219bool GroupConditionVendorClassID::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1220                                        const OptUserClassId &a_ridUserClass) const
     1221{
     1222    RT_NOREF(a_ridClient, a_ridUserClass);
     1223    return matchClassId(a_ridVendorClass.present(), a_ridVendorClass.value());
     1224}
     1225
     1226
     1227bool GroupConditionVendorClassIDWildcard::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1228                                                const OptUserClassId &a_ridUserClass) const
     1229{
     1230    RT_NOREF(a_ridClient, a_ridUserClass);
     1231    return matchClassId(a_ridVendorClass.present(), a_ridVendorClass.value(), true /*fWildcard*/);
     1232}
     1233
     1234
     1235bool GroupConditionUserClassID::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1236                                      const OptUserClassId &a_ridUserClass) const
     1237{
     1238    RT_NOREF(a_ridClient, a_ridVendorClass);
     1239    return matchClassId(a_ridVendorClass.present(), a_ridUserClass.value());
     1240}
     1241
     1242
     1243bool GroupConditionUserClassIDWildcard::match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     1244                                              const OptUserClassId &a_ridUserClass) const
     1245{
     1246    RT_NOREF(a_ridClient, a_ridVendorClass);
     1247    return matchClassId(a_ridVendorClass.present(), a_ridUserClass.value(), true /*fWildcard*/);
     1248}
     1249
  • trunk/src/VBox/NetworkServices/Dhcpd/Config.h

    r79800 r79810  
    9797
    9898
    99 #if 0 /* later */
    10099/**
    101100 * Group membership condition.
    102101 */
    103 class GroupConditionBase
     102class GroupCondition
    104103{
    105104protected:
    106105    /** The value. */
    107106    RTCString   m_strValue;
    108 
    109 public:
    110 
    111 };
    112 #endif
     107    /** Inclusive (true) or exclusive (false), latter takes precedency. */
     108    bool        m_fInclusive;
     109
     110public:
     111    virtual ~GroupCondition()
     112    {}
     113
     114    virtual int  initCondition(const char *a_pszValue, bool a_fInclusive);
     115    virtual bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     116                       const OptUserClassId &a_ridUserClass) const RT_NOEXCEPT = 0;
     117
     118    /** @name accessors
     119     * @{  */
     120    RTCString const    &getValue()     const RT_NOEXCEPT { return m_strValue; }
     121    bool                getInclusive() const RT_NOEXCEPT { return m_fInclusive; }
     122    /** @} */
     123
     124protected:
     125    bool matchClassId(bool a_fPresent, std::vector<uint8_t> const &a_rBytes, bool fWildcard = false) const RT_NOEXCEPT;
     126};
     127
     128/** MAC condition. */
     129class GroupConditionMAC : public GroupCondition
     130{
     131private:
     132    RTMAC   m_MACAddress;
     133public:
     134    int  initCondition(const char *a_pszValue, bool a_fInclusive) RT_OVERRIDE;
     135    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     136               const OptUserClassId &a_ridUserClass) const RT_OVERRIDE;
     137};
     138
     139/** MAC wildcard condition. */
     140class GroupConditionMACWildcard : public GroupCondition
     141{
     142public:
     143    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     144               const OptUserClassId &a_ridUserClass) const RT_OVERRIDE;
     145};
     146
     147/** Vendor class ID condition. */
     148class GroupConditionVendorClassID : public GroupCondition
     149{
     150public:
     151    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     152               const OptUserClassId &a_ridUserClass) const RT_OVERRIDE;
     153};
     154
     155/** Vendor class ID wildcard condition. */
     156class GroupConditionVendorClassIDWildcard : public GroupCondition
     157{
     158public:
     159    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     160               const OptUserClassId &a_ridUserClass) const RT_OVERRIDE;
     161};
     162
     163/** User class ID condition. */
     164class GroupConditionUserClassID : public GroupCondition
     165{
     166public:
     167    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     168               const OptUserClassId &a_ridUserClass) const RT_OVERRIDE;
     169};
     170
     171/** User class ID wildcard condition. */
     172class GroupConditionUserClassIDWildcard : public GroupCondition
     173{
     174public:
     175    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass,
     176               const OptUserClassId &a_ridUserClass) const RT_OVERRIDE;
     177};
    113178
    114179
     
    118183class GroupConfig : public ConfigLevelBase
    119184{
    120 public:
     185private:
     186    typedef std::vector<GroupCondition *> GroupConditionVec;
     187
    121188    /** The group name. */
    122     RTCString       m_strName;
     189    RTCString           m_strName;
     190    /** Vector containing the inclusive membership conditions (must match one). */
     191    GroupConditionVec   m_Inclusive;
     192    /** Vector containing the exclusive membership conditions (must match none). */
     193    GroupConditionVec   m_Exclusive;
    123194
    124195public:
     
    129200
    130201    void initFromXml(xml::ElementNode const *pElm, bool fStrict) RT_OVERRIDE;
    131     const char *getType() const RT_NOEXCEPT RT_OVERRIDE { return "group"; }
    132     const char *getName() const RT_NOEXCEPT RT_OVERRIDE { return m_strName.c_str(); }
     202    bool match(const ClientId &a_ridClient, const OptVendorClassId &a_ridVendorClass, const OptUserClassId &a_ridUserClass) const;
    133203
    134204    /** @name Accessors
    135205     * @{ */
     206    const char         *getType() const RT_NOEXCEPT RT_OVERRIDE { return "group"; }
     207    const char         *getName() const RT_NOEXCEPT RT_OVERRIDE { return m_strName.c_str(); }
    136208    RTCString const    &getGroupName() const RT_NOEXCEPT        { return m_strName; }
    137209    /** @} */
  • trunk/src/VBox/NetworkServices/Dhcpd/DhcpMessage.cpp

    r79568 r79810  
    2424#include "DhcpOptions.h"
    2525
     26#include <iprt/ctype.h>
    2627#include <iprt/string.h>
    2728
     
    279280    }
    280281
    281     bool fHeader = true;
    282282    for (rawopts_t::const_iterator it = m_rawopts.begin(); it != m_rawopts.end(); ++it)
    283283    {
     
    294294
    295295            default:
    296                 if (fHeader)
    297                 {
    298                     LogRel((" other options:"));
    299                     fHeader = false;
    300                 }
    301                 LogRel((" %d", optcode));
    302                 break;
     296            {
     297                size_t const   cbBytes = it->second.size();
     298                uint8_t const *pbBytes = &it->second.front();
     299                bool fAllPrintable = true;
     300                for (size_t off = 0; off < cbBytes; off++)
     301                    if (!RT_C_IS_PRINT((char )pbBytes[off]))
     302                    {
     303                        fAllPrintable = false;
     304                        break;
     305                    }
     306                if (fAllPrintable)
     307                    LogRel(("  %2d: '%.*s'\n", optcode, cbBytes, pbBytes));
     308                else
     309                    LogRel(("  %2d: %.*Rhxs\n", optcode, cbBytes, pbBytes));
     310            }
    303311        }
    304312    }
    305     if (!fHeader)
    306         LogRel(("\n"));
    307313}
    308314
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