/** * Converts an stringified IPv4 address into the RTNETADDRIPV4 representation. * * @todo This should be move to some generic part of the runtime. * * @returns VINF_SUCCESS on success, VERR_GETOPT_INVALID_ARGUMENT_FORMAT on * failure. * * @param pszValue The value to convert. * @param pAddr Where to store the result. */ static int rtgetoptConvertIPv4Addr(const char *pszValue, PRTNETADDRIPV4 pAddr) { char *pszNext; int rc = RTStrToUInt8Ex(RTStrStripL(pszValue), &pszNext, 10, &pAddr->au8[0]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; if (*pszNext++ != '.') return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[1]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; if (*pszNext++ != '.') return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[2]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; if (*pszNext++ != '.') return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[3]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES) return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; pszNext = RTStrStripL(pszNext); if (*pszNext) return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; return VINF_SUCCESS; }
DECLHIDDEN(int) rtNetStrToIPv4AddrEx(const char *pcszAddr, PRTNETADDRIPV4 pAddr, char **ppszNext) { char *pszNext; int rc; AssertPtrReturn(pcszAddr, VERR_INVALID_PARAMETER); AssertPtrReturn(pAddr, VERR_INVALID_PARAMETER); rc = RTStrToUInt8Ex(pcszAddr, &pszNext, 10, &pAddr->au8[0]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_INVALID_PARAMETER; if (*pszNext++ != '.') return VERR_INVALID_PARAMETER; rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[1]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_INVALID_PARAMETER; if (*pszNext++ != '.') return VERR_INVALID_PARAMETER; rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[2]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_INVALID_PARAMETER; if (*pszNext++ != '.') return VERR_INVALID_PARAMETER; rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &pAddr->au8[3]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES && rc != VWRN_TRAILING_CHARS) return VERR_INVALID_PARAMETER; if (ppszNext != NULL) *ppszNext = pszNext; return VINF_SUCCESS; }
RTDECL(bool) RTNetIsIPv4AddrStr(const char *pszAddress) { static char const s_szIpV4Digits[] = "0123456789."; size_t cchAddress = strlen(pszAddress); if (cchAddress < 7 || cchAddress > 15) return false; const char *pStart, *pFrom, *pTo, *pNow; pStart = pNow = pFrom = pTo = pszAddress; unsigned cOctets = 0; while (*pNow != '\0') { const char *pChar = (const char *)memchr(s_szIpV4Digits, *pNow, sizeof(s_szIpV4Digits) - 1); const char *pDigit = (const char *)memchr(s_szIpV4Digits, *pNow, sizeof(s_szIpV4Digits) - 2); const char *pNext = pNow + 1; if (!pChar) return false; if (pDigit && *pNext != '\0') { pTo = pNow; pNow++; continue; } if (*pNow == '.' || *pNext == '\0') { if (*pNext == '\0') pTo = pNow; size_t cchSub = pTo - pFrom; if (cchSub > 2) return false; char szDummy[4] = { 0, 0, 0, 0 }; memcpy(szDummy, pFrom, cchSub + 1); int rc = RTStrToUInt8Ex(szDummy, NULL, 10, NULL); if (rc != VINF_SUCCESS) return false; cOctets++; if (cOctets > 4) return false; pFrom = pNext; } pNow++; } if (cOctets != 4) return false; return true; }
/** * Converts an stringified Ethernet MAC address into the RTMAC representation. * * @returns VINF_SUCCESS on success. * * @param pszValue The value to convert. * @param pAddr Where to store the result. */ RTDECL(int) RTNetStrToMacAddr(const char *pszValue, PRTMAC pAddr) { /* * Not quite sure if I should accept stuff like "08::27:::1" here... * The code is accepting "::" patterns now, except for for the first * and last parts. */ /* first */ char *pszNext; int rc = RTStrToUInt8Ex(RTStrStripL(pszValue), &pszNext, 16, &pAddr->au8[0]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; if (*pszNext++ != ':') return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; /* middle */ for (unsigned i = 1; i < 5; i++) { if (*pszNext == ':') pAddr->au8[i] = 0; else { rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &pAddr->au8[i]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS) return rc; if (*pszNext != ':') return VERR_INVALID_PARAMETER; } pszNext++; } /* last */ rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &pAddr->au8[5]); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_SPACES) return rc; pszNext = RTStrStripL(pszNext); if (*pszNext) return VERR_INVALID_PARAMETER; return VINF_SUCCESS; }
static char *rtUriPercentDecodeN(const char *pszString, size_t cchMax) { if (!pszString) return NULL; int rc = VINF_SUCCESS; size_t cbLen = RT_MIN(strlen(pszString), cchMax); /* The new string can only get smaller. */ char *pszNew = (char*)RTMemAlloc(cbLen + 1); if (!pszNew) return NULL; char *pszRes = NULL; size_t iIn = 0; size_t iOut = 0; while(iIn < cbLen) { if (pszString[iIn] == '%') { /* % encoding means the percent sign and exactly 2 hexadecimal * digits describing the ASCII number of the character. */ ++iIn; char szNum[3]; szNum[0] = pszString[iIn++]; szNum[1] = pszString[iIn++]; szNum[2] = '\0'; uint8_t u8; rc = RTStrToUInt8Ex(szNum, NULL, 16, &u8); if (RT_FAILURE(rc)) break; pszNew[iOut] = u8; } else pszNew[iOut] = pszString[iIn++]; ++iOut; } if (RT_SUCCESS(rc)) { pszNew[iOut] = '\0'; if (iOut != iIn) { /* If the source and target strings have different size, recreate * the target string with the correct size. */ pszRes = RTStrDupN(pszNew, iOut); RTStrFree(pszNew); } else pszRes = pszNew; } else RTStrFree(pszNew); return pszRes; }
/* static */ DECLCALLBACK(int) Guest::i_staticEnumStatsCallback(const char *pszName, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit, STAMVISIBILITY enmVisiblity, const char *pszDesc, void *pvUser) { AssertLogRelMsgReturn(enmType == STAMTYPE_COUNTER, ("Unexpected sample type %d ('%s')\n", enmType, pszName), VINF_SUCCESS); AssertLogRelMsgReturn(enmUnit == STAMUNIT_BYTES, ("Unexpected sample unit %d ('%s')\n", enmUnit, pszName), VINF_SUCCESS); /* Get the base name w/ slash. */ const char *pszLastSlash = strrchr(pszName, '/'); AssertLogRelMsgReturn(pszLastSlash, ("Unexpected sample '%s'\n", pszName), VINF_SUCCESS); /* Receive or transmit? */ bool fRx; if (!strcmp(pszLastSlash, "/BytesReceived")) fRx = true; else if (!strcmp(pszLastSlash, "/BytesTransmitted")) fRx = false; else AssertLogRelMsgFailedReturn(("Unexpected sample '%s'\n", pszName), VINF_SUCCESS); #if 0 /* not used for anything, so don't bother parsing it. */ /* Find start of instance number. ASSUMES '/Public/Net/Name<Instance digits>/Bytes...' */ do --pszLastSlash; while (pszLastSlash > pszName && RT_C_IS_DIGIT(*pszLastSlash)); pszLastSlash++; uint8_t uInstance; int rc = RTStrToUInt8Ex(pszLastSlash, NULL, 10, &uInstance); AssertLogRelMsgReturn(RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG && rc != VWRN_NEGATIVE_UNSIGNED, ("%Rrc '%s'\n", rc, pszName), VINF_SUCCESS) #endif /* Add the bytes to our counters. */ PSTAMCOUNTER pCnt = (PSTAMCOUNTER)pvSample; Guest *pGuest = (Guest *)pvUser; uint64_t cb = pCnt->c; #if 0 LogFlowFunc(("%s i=%u d=%s %llu bytes\n", pszName, uInstance, fRx ? "RX" : "TX", cb)); #else LogFlowFunc(("%s d=%s %llu bytes\n", pszName, fRx ? "RX" : "TX", cb)); #endif if (fRx) pGuest->mNetStatRx += cb; else pGuest->mNetStatTx += cb; return VINF_SUCCESS; }
/* * XXX: TODO: Share decoding code with DHCPServer::addOption. */ static int parseDhcpOptionText(const char *pszText, int *pOptCode, char **ppszOptText, int *pOptEncoding) { uint8_t u8Code; uint32_t u32Enc; char *pszNext; int rc; rc = RTStrToUInt8Ex(pszText, &pszNext, 10, &u8Code); if (!RT_SUCCESS(rc)) return VERR_PARSE_ERROR; switch (*pszNext) { case ':': /* support legacy format too */ { u32Enc = 0; break; } case '=': { u32Enc = 1; break; } case '@': { rc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 10, &u32Enc); if (!RT_SUCCESS(rc)) return VERR_PARSE_ERROR; if (*pszNext != '=') return VERR_PARSE_ERROR; break; } default: return VERR_PARSE_ERROR; } *pOptCode = u8Code; *ppszOptText = pszNext + 1; *pOptEncoding = (int)u32Enc; return VINF_SUCCESS; }
/* static */ int Guest::staticEnumStatsCallback(const char *pszName, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit, STAMVISIBILITY enmVisiblity, const char *pszDesc, void *pvUser) { PSTAMCOUNTER pCnt = (PSTAMCOUNTER)pvSample; char *pszEnd = strrchr((char*)pszName, '/'); if (pszEnd) { bool fRx; uint8_t uInstance = 0; switch (pszEnd[1]) { case 'R': fRx = true; break; case 'T': fRx = false; break; default: LogRel(("Failed to parse the name of network stat counter (unknown counter): %s\n", pszName)); return VINF_SUCCESS; } do --pszEnd; while (pszEnd > pszName && RT_C_IS_DIGIT(*pszEnd)); if (RT_SUCCESS(RTStrToUInt8Ex(pszEnd + 1, NULL, 10, &uInstance))) { Guest *pGuest = (Guest *)pvUser; LogFlowFunc(("%s i=%u d=%s %llu %s\n", pszName, uInstance, fRx ? "RX" : "TX", pCnt->c, STAMR3GetUnit(enmUnit))); if (fRx) pGuest->mNetStatRx += pCnt->c; else pGuest->mNetStatTx += pCnt->c; } else LogRel(("Failed to extract the device instance from the name of network stat counter: %s\n", pszEnd)); } else LogRel(("Failed to parse the name of network stat counter (no slash): %s\n", pszName)); return VINF_SUCCESS; }
static int fillDhcpOption(RawOption &opt, const std::string &OptText, int OptEncoding) { int rc; if (OptEncoding == DhcpOptEncoding_Hex) { if (OptText.empty()) return VERR_INVALID_PARAMETER; size_t cbRawOpt = 0; char *pszNext = const_cast<char *>(OptText.c_str()); while (*pszNext != '\0') { if (cbRawOpt >= RT_ELEMENTS(opt.au8RawOpt)) return VERR_INVALID_PARAMETER; uint8_t u8Byte; rc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &u8Byte); if (!RT_SUCCESS(rc)) return rc; if (*pszNext == ':') ++pszNext; else if (*pszNext != '\0') return VERR_PARSE_ERROR; opt.au8RawOpt[cbRawOpt] = u8Byte; ++cbRawOpt; } opt.cbRawOpt = (uint8_t)cbRawOpt; } else if (OptEncoding == DhcpOptEncoding_Legacy) { /* * XXX: TODO: encode "known" option opt.u8OptId */ return VERR_INVALID_PARAMETER; } return VINF_SUCCESS; }
/** * Attempts to convert an ISO date string to a time structure. * * We're a little forgiving with zero padding, unspecified parts, and leading * and trailing spaces. * * @retval pTime on success, * @retval NULL on failure. * @param pTime Where to store the time on success. * @param pszString The ISO date string to convert. */ RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString) { /* Ignore leading spaces. */ while (RT_C_IS_SPACE(*pszString)) pszString++; /* * Init non date & time parts. */ pTime->fFlags = RTTIME_FLAGS_TYPE_LOCAL; pTime->offUTC = 0; /* * The day part. */ /* Year */ int rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->i32Year); if (rc != VWRN_TRAILING_CHARS) return NULL; bool const fLeapYear = rtTimeIsLeapYear(pTime->i32Year); if (fLeapYear) pTime->fFlags |= RTTIME_FLAGS_LEAP_YEAR; if (*pszString++ != '-') return NULL; /* Month of the year. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Month); if (rc != VWRN_TRAILING_CHARS) return NULL; if (pTime->u8Month == 0 || pTime->u8Month > 12) return NULL; if (*pszString++ != '-') return NULL; /* Day of month.*/ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8MonthDay); if (rc != VWRN_TRAILING_CHARS && rc != VINF_SUCCESS) return NULL; unsigned const cDaysInMonth = fLeapYear ? g_acDaysInMonthsLeap[pTime->u8Month - 1] : g_acDaysInMonths[pTime->u8Month - 1]; if (pTime->u8MonthDay == 0 || pTime->u8MonthDay > cDaysInMonth) return NULL; /* Calculate year day. */ pTime->u16YearDay = pTime->u8MonthDay - 1 + (fLeapYear ? g_aiDayOfYearLeap[pTime->u8Month - 1] : g_aiDayOfYear[pTime->u8Month - 1]); /* * The time part. */ if (*pszString++ != 'T') return NULL; /* Hour. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Hour); if (rc != VWRN_TRAILING_CHARS) return NULL; if (pTime->u8Hour > 23) return NULL; if (*pszString++ != ':') return NULL; /* Minute. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute); if (rc != VWRN_TRAILING_CHARS) return NULL; if (pTime->u8Minute > 59) return NULL; if (*pszString++ != ':') return NULL; /* Second. */ rc = RTStrToUInt8Ex(pszString, (char **)&pszString, 10, &pTime->u8Minute); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES) return NULL; if (pTime->u8Second > 59) return NULL; /* Nanoseconds is optional and probably non-standard. */ if (*pszString == '.') { rc = RTStrToUInt32Ex(pszString + 1, (char **)&pszString, 10, &pTime->u32Nanosecond); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES) return NULL; if (pTime->u32Nanosecond >= 1000000000) return NULL; } else pTime->u32Nanosecond = 0; /* * Time zone. */ if (*pszString == 'Z') { pszString++; pTime->fFlags &= ~RTTIME_FLAGS_TYPE_MASK; pTime->fFlags |= ~RTTIME_FLAGS_TYPE_UTC; pTime->offUTC = 0; } else if ( *pszString == '+' || *pszString == '-') { rc = RTStrToInt32Ex(pszString, (char **)&pszString, 10, &pTime->offUTC); if (rc != VINF_SUCCESS && rc != VWRN_TRAILING_CHARS && rc != VWRN_TRAILING_SPACES) return NULL; } /* else: No time zone given, local with offUTC = 0. */ /* * The rest of the string should be blanks. */ char ch; while ((ch = *pszString++) != '\0') if (!RT_C_IS_BLANK(ch)) return NULL; return pTime; }
RTDECL(int) RTCidrStrToIPv4(const char *pszAddress, PRTIPV4ADDR pNetwork, PRTIPV4ADDR pNetmask) { uint8_t cBits; uint8_t addr[4]; uint32_t u32Netmask; uint32_t u32Network; const char *psz = pszAddress; const char *pszNetmask; char *pszNext; int rc = VINF_SUCCESS; int cDelimiter = 0; int cDelimiterLimit = 0; AssertPtrReturn(pszAddress, VERR_INVALID_PARAMETER); AssertPtrReturn(pNetwork, VERR_INVALID_PARAMETER); AssertPtrReturn(pNetmask, VERR_INVALID_PARAMETER); pszNetmask = RTStrStr(psz, "/"); *(uint32_t *)addr = 0; if (!pszNetmask) cBits = 32; else { rc = RTStrToUInt8Ex(pszNetmask + 1, &pszNext, 10, &cBits); if ( RT_FAILURE(rc) || cBits > 32 || rc != VINF_SUCCESS) /* No trailing symbols are acceptable after the digit */ return VERR_INVALID_PARAMETER; } u32Netmask = ~(uint32_t)((1<< (32 - cBits)) - 1); if (cBits <= 8) cDelimiterLimit = 0; else if (cBits <= 16) cDelimiterLimit = 1; else if (cBits <= 24) cDelimiterLimit = 2; else if (cBits <= 32) cDelimiterLimit = 3; for (;;) { rc = RTStrToUInt8Ex(psz, &pszNext, 10, &addr[cDelimiter]); if ( RT_FAILURE(rc) || rc == VWRN_NUMBER_TOO_BIG) return VERR_INVALID_PARAMETER; if (*pszNext == '.') cDelimiter++; else if ( cDelimiter >= cDelimiterLimit && ( *pszNext == '\0' || *pszNext == '/')) break; else return VERR_INVALID_PARAMETER; if (cDelimiter > 3) /* not more than four octets */ return VERR_INVALID_PARAMETER; psz = pszNext + 1; } u32Network = RT_MAKE_U32_FROM_U8(addr[3], addr[2], addr[1], addr[0]); /* Corner case: see RFC 790 page 2 and RFC 4632 page 6. */ if ( addr[0] == 0 && ( *(uint32_t *)addr != 0 || u32Netmask == (uint32_t)~0)) return VERR_INVALID_PARAMETER; if ((u32Network & ~u32Netmask) != 0) return VERR_INVALID_PARAMETER; *pNetmask = u32Netmask; *pNetwork = u32Network; return VINF_SUCCESS; }
bool writeQuoted(enum ENMFORMAT enmFormat, const char *pcszQuoted) { /* Was the last character seen a back slash? */ bool fEscaped = false; /* Was the last character seen an argument separator (an unescaped space)? */ bool fNextArgument = false; if (enmFormat == FORMAT_SHELL) if (!outputCharacter('\'')) return false; for (; *pcszQuoted; ++pcszQuoted) { if (fEscaped) { bool fRc = true; const char (*pachEscapes)[2]; fEscaped = false; /* One-letter escapes. */ for (pachEscapes = aachEscapes; (*pachEscapes)[0]; ++pachEscapes) if (*pcszQuoted == (*pachEscapes)[0]) { if (!escapeAndOutputCharacter(enmFormat, (*pachEscapes)[1])) return false; break; } if ((*pachEscapes)[0]) continue; /* Octal. */ if (*pcszQuoted >= '0' && *pcszQuoted <= '7') { uint8_t cNum; char *pchNext; char achDigits[4]; int rc; RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted); rc = RTStrToUInt8Ex(achDigits, &pchNext, 8, &cNum); if (rc == VWRN_NUMBER_TOO_BIG) { RTStrmPrintf(g_pStdErr, "Invalid octal sequence at \"%.16s\"\n", pcszQuoted - 1); return false; } if (!escapeAndOutputCharacter(enmFormat, cNum)) return false; pcszQuoted += pchNext - achDigits - 1; continue; } /* Hexadecimal. */ if (*pcszQuoted == 'x') { uint8_t cNum; char *pchNext; char achDigits[3]; int rc; RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted + 1); rc = RTStrToUInt8Ex(achDigits, &pchNext, 16, &cNum); if ( rc == VWRN_NUMBER_TOO_BIG || rc == VWRN_NEGATIVE_UNSIGNED || RT_FAILURE(rc)) { RTStrmPrintf(g_pStdErr, "Invalid hexadecimal sequence at \"%.16s\"\n", pcszQuoted - 1); return false; } if (!escapeAndOutputCharacter(enmFormat, cNum)) return false; pcszQuoted += pchNext - achDigits; continue; } /* Output anything else non-zero as is. */ if (*pcszQuoted) { if (!escapeAndOutputCharacter(enmFormat, *pcszQuoted)) return false; continue; } RTStrmPrintf(g_pStdErr, "Trailing back slash in argument.\n"); return false; } /* Argument separator. */ if (*pcszQuoted == ' ') { if (!fNextArgument && !outputArgumentSeparator(enmFormat)) return false; fNextArgument = true; continue; } else fNextArgument = false; /* Start of escape sequence. */ if (*pcszQuoted == '\\') { fEscaped = true; continue; } /* Anything else. */ if (!outputCharacter(*pcszQuoted)) return false; } if (enmFormat == FORMAT_SHELL) if (!outputCharacter('\'')) return false; return true; }
int DHCPServer::addOption(settings::DhcpOptionMap &aMap, DhcpOpt_T aOption, const com::Utf8Str &aValue) { settings::DhcpOptValue OptValue; if (aOption != 0) { OptValue = settings::DhcpOptValue(aValue, DhcpOptEncoding_Legacy); } /* * This is a kludge to sneak in option encoding information * through existing API. We use option 0 and supply the real * option/value in the same format that encodeOption() above * produces for getter methods. */ else { uint8_t u8Code; uint32_t u32Enc; char *pszNext; int rc; rc = RTStrToUInt8Ex(aValue.c_str(), &pszNext, 10, &u8Code); if (!RT_SUCCESS(rc)) return VERR_PARSE_ERROR; switch (*pszNext) { case ':': /* support legacy format too */ { u32Enc = DhcpOptEncoding_Legacy; break; } case '=': { u32Enc = DhcpOptEncoding_Hex; break; } case '@': { rc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 10, &u32Enc); if (!RT_SUCCESS(rc)) return VERR_PARSE_ERROR; if (*pszNext != '=') return VERR_PARSE_ERROR; break; } default: return VERR_PARSE_ERROR; } aOption = (DhcpOpt_T)u8Code; OptValue = settings::DhcpOptValue(pszNext + 1, (DhcpOptEncoding_T)u32Enc); } aMap[aOption] = OptValue; return VINF_SUCCESS; }