void genControlInfo(int* oid, size_t oid_size, QueryData& results, const std::map<std::string, std::string>& config) { // Get control size size_t response_size = CTL_MAX_VALUE; char response[CTL_MAX_VALUE + 1] = {0}; if (sysctl(oid, oid_size, response, &response_size, 0, 0) != 0) { // Cannot request MIB data. return; } // Data is output, but no way to determine type (long, int, string, struct). Row r; r["oid"] = stringFromMIB(oid, oid_size); r["current_value"] = std::string(response); r["type"] = "string"; results.push_back(r); }
void genControlInfo(int* oid, size_t oid_size, QueryData& results, const std::map<std::string, std::string>& config) { Row r; if (oid_size == 0) { return; } r["oid"] = stringFromMIB(oid, oid_size); // Request the description (the canonical name) for the MIB. char response[CTL_MAX_VALUE] = {0}; size_t response_size = CTL_MAX_VALUE; int request[CTL_MAXNAME + 2] = {0, CTL_DEBUG_DESCRIPTION}; memcpy(request + 2, oid, oid_size * sizeof(int)); if (sysctl(request, oid_size + 2, response, &response_size, 0, 0) != 0) { return; } r["name"] = std::string(response); if (oid[0] > 0 && oid[0] < static_cast<int>(kControlNames.size())) { r["subsystem"] = kControlNames[oid[0]]; } // Now request structure type. request[1] = CTL_DEBUG_TYPE; if (sysctl(request, oid_size + 2, response, &response_size, 0, 0) != 0) { // Cannot request MIB type (int, string, struct, etc). return; } size_t oid_type = 0; if (response_size > 0) { oid_type = ((size_t)response[0] & CTLTYPE); if (oid_type < kControlTypes.size()) { r["type"] = kControlTypes[((int)response[0])]; } } // Finally request MIB value. if (oid_type > CTLTYPE_NODE && oid_type < CTLTYPE_OPAQUE) { size_t value_size = 0; sysctl(oid, oid_size, 0, &value_size, 0, 0); if (value_size > CTL_MAX_VALUE) { // If the value size is larger than the max value, limit. value_size = CTL_MAX_VALUE; } sysctl(oid, oid_size, response, &value_size, 0, 0); if (oid_type == CTLTYPE_INT) { unsigned int value; memcpy(&value, response, sizeof(int)); r["current_value"] = INTEGER(value); } else if (oid_type == CTLTYPE_STRING) { r["current_value"] = std::string(response); } else if (oid_type == CTLTYPE_QUAD) { unsigned long long value; memcpy(&value, response, value_size); } } // If this MIB was set using sysctl.conf add the value. if (config.count(r.at("name")) > 0) { r["config_value"] = config.at(r["name"]); } results.push_back(r); }
void genControlInfo(int* oid, size_t oid_size, QueryData& results, const std::map<std::string, std::string>& config) { Row r; if (oid_size == 0) { return; } r["oid"] = stringFromMIB(oid, oid_size); // Request the description (the canonical name) for the MIB. char response[CTL_MAX_VALUE] = {0}; size_t response_size = CTL_MAX_VALUE; int request[CTL_MAXNAME + 2] = {0, CTL_DEBUG_DESCRIPTION}; memcpy(request + 2, oid, oid_size * sizeof(int)); if (sysctl(request, oid_size + 2, response, &response_size, 0, 0) != 0) { return; } r["name"] = std::string(response); if (oid[0] > 0 && oid[0] < static_cast<int>(kControlNames.size())) { r["subsystem"] = kControlNames[oid[0]]; } // Now request structure type. response_size = CTL_MAX_VALUE; request[1] = CTL_DEBUG_TYPE; if (sysctl(request, oid_size + 2, response, &response_size, 0, 0) != 0) { // Cannot request MIB type (int, string, struct, etc). return; } size_t oid_type = 0; if (response_size > 0) { oid_type = ((size_t)response[0] & CTLTYPE); if ((oid_type == 0 || oid_type == CTLTYPE_INT) && response_size > 4) { // For whatever reason, macOS defines fewer CTLTYPE's than BSD, and // sometimes uses the format character instead of (or in addition to) // the CTLTYPE to specify the type. Here we detect a few such cases and // map them to CTLTYPE's. // TODO: Both CTLTYPE_INT and CTLTYPE_QUAD can be specified as unsigned // using a similar method. char type_char = response[4]; switch (type_char) { case 'I': oid_type = CTLTYPE_INT; break; case 'L': if (sizeof(long) == sizeof(long long)) { oid_type = CTLTYPE_QUAD; } else if (sizeof(long) == sizeof(int)) { oid_type = CTLTYPE_INT; } break; case 'S': oid_type = CTLTYPE_STRUCT; break; case 'Q': oid_type = CTLTYPE_QUAD; break; // Otherwise leave the type as it was; we have no additional knowledge } } if (oid_type < kControlTypes.size()) { r["type"] = kControlTypes[oid_type]; } } // Finally request MIB value. if (oid_type > CTLTYPE_NODE && oid_type < CTLTYPE_OPAQUE) { size_t value_size = 0; sysctl(oid, oid_size, 0, &value_size, 0, 0); if (value_size > CTL_MAX_VALUE) { // If the value size is larger than the max value, limit. value_size = CTL_MAX_VALUE; } sysctl(oid, oid_size, response, &value_size, 0, 0); if (oid_type == CTLTYPE_INT) { unsigned int value; memcpy(&value, response, sizeof(int)); r["current_value"] = INTEGER(value); } else if (oid_type == CTLTYPE_STRING) { r["current_value"] = std::string(response); } else if (oid_type == CTLTYPE_QUAD) { unsigned long long value; memcpy(&value, response, sizeof(unsigned long long)); r["current_value"] = INTEGER(value); } } // If this MIB was set using sysctl.conf add the value. if (config.count(r.at("name")) > 0) { r["config_value"] = config.at(r["name"]); } results.push_back(r); }