1f085d91dSPatrick Venture /* 2f085d91dSPatrick Venture * Copyright 2019 Google Inc. 3f085d91dSPatrick Venture * 4f085d91dSPatrick Venture * Licensed under the Apache License, Version 2.0 (the "License"); 5f085d91dSPatrick Venture * you may not use this file except in compliance with the License. 6f085d91dSPatrick Venture * You may obtain a copy of the License at 7f085d91dSPatrick Venture * 8f085d91dSPatrick Venture * http://www.apache.org/licenses/LICENSE-2.0 9f085d91dSPatrick Venture * 10f085d91dSPatrick Venture * Unless required by applicable law or agreed to in writing, software 11f085d91dSPatrick Venture * distributed under the License is distributed on an "AS IS" BASIS, 12f085d91dSPatrick Venture * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f085d91dSPatrick Venture * See the License for the specific language governing permissions and 14f085d91dSPatrick Venture * limitations under the License. 15f085d91dSPatrick Venture */ 16f085d91dSPatrick Venture 17f085d91dSPatrick Venture #include "handler.hpp" 18f085d91dSPatrick Venture 19d2037c6aSPatrick Venture #include "errors.hpp" 20d2037c6aSPatrick Venture 21d2037c6aSPatrick Venture #include <ipmid/api.h> 22d2037c6aSPatrick Venture 23*bb90d4fdSPatrick Venture #include <cinttypes> 24d2037c6aSPatrick Venture #include <cstdio> 25d2037c6aSPatrick Venture #include <filesystem> 26d2037c6aSPatrick Venture #include <fstream> 27d2037c6aSPatrick Venture #include <sstream> 28d2037c6aSPatrick Venture #include <string> 29d2037c6aSPatrick Venture #include <tuple> 30d2037c6aSPatrick Venture 31f085d91dSPatrick Venture // The phosphor-host-ipmi daemon requires a configuration that maps 32f085d91dSPatrick Venture // the if_name to the IPMI LAN channel. However, that doesn't strictly 33f085d91dSPatrick Venture // define which is meant to be used for NCSI. 34f085d91dSPatrick Venture #ifndef NCSI_IPMI_CHANNEL 35f085d91dSPatrick Venture #define NCSI_IPMI_CHANNEL 1 36f085d91dSPatrick Venture #endif 37f085d91dSPatrick Venture 38f085d91dSPatrick Venture #ifndef NCSI_IF_NAME 39f085d91dSPatrick Venture #define NCSI_IF_NAME eth0 40f085d91dSPatrick Venture #endif 41f085d91dSPatrick Venture 42f085d91dSPatrick Venture // To deal with receiving a string without quotes. 43f085d91dSPatrick Venture #define QUOTE(name) #name 44f085d91dSPatrick Venture #define STR(macro) QUOTE(macro) 45f085d91dSPatrick Venture #define NCSI_IF_NAME_STR STR(NCSI_IF_NAME) 46f085d91dSPatrick Venture 47f085d91dSPatrick Venture namespace google 48f085d91dSPatrick Venture { 49f085d91dSPatrick Venture namespace ipmi 50f085d91dSPatrick Venture { 51d2037c6aSPatrick Venture namespace fs = std::filesystem; 52f085d91dSPatrick Venture 53f085d91dSPatrick Venture std::tuple<std::uint8_t, std::string> Handler::getEthDetails() const 54f085d91dSPatrick Venture { 55f085d91dSPatrick Venture return std::make_tuple(NCSI_IPMI_CHANNEL, NCSI_IF_NAME_STR); 56f085d91dSPatrick Venture } 57f085d91dSPatrick Venture 58d2037c6aSPatrick Venture std::int64_t Handler::getRxPackets(const std::string& name) const 59d2037c6aSPatrick Venture { 60d2037c6aSPatrick Venture std::ostringstream opath; 61d2037c6aSPatrick Venture opath << "/sys/class/net/" << name << "/statistics/rx_packets"; 62d2037c6aSPatrick Venture std::string path = opath.str(); 63d2037c6aSPatrick Venture 64d2037c6aSPatrick Venture // Minor sanity & security check (of course, I'm less certain if unicode 65d2037c6aSPatrick Venture // comes into play here. 66d2037c6aSPatrick Venture // 67d2037c6aSPatrick Venture // Basically you can't easily inject ../ or /../ into the path below. 68d2037c6aSPatrick Venture if (name.find("/") != std::string::npos) 69d2037c6aSPatrick Venture { 70d2037c6aSPatrick Venture std::fprintf(stderr, "Invalid or illegal name: '%s'\n", name.c_str()); 71d2037c6aSPatrick Venture throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST); 72d2037c6aSPatrick Venture } 73d2037c6aSPatrick Venture 74d2037c6aSPatrick Venture std::error_code ec; 75d2037c6aSPatrick Venture if (!fs::exists(path, ec)) 76d2037c6aSPatrick Venture { 77d2037c6aSPatrick Venture std::fprintf(stderr, "Path: '%s' doesn't exist.\n", path.c_str()); 78d2037c6aSPatrick Venture throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST); 79d2037c6aSPatrick Venture } 80d2037c6aSPatrick Venture // We're uninterested in the state of ec. 81d2037c6aSPatrick Venture 82d2037c6aSPatrick Venture int64_t count = 0; 83d2037c6aSPatrick Venture std::ifstream ifs; 84d2037c6aSPatrick Venture ifs.exceptions(std::ifstream::failbit); 85d2037c6aSPatrick Venture try 86d2037c6aSPatrick Venture { 87d2037c6aSPatrick Venture ifs.open(path); 88d2037c6aSPatrick Venture ifs >> count; 89d2037c6aSPatrick Venture } 90d2037c6aSPatrick Venture catch (std::ios_base::failure& fail) 91d2037c6aSPatrick Venture { 92d2037c6aSPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 93d2037c6aSPatrick Venture } 94d2037c6aSPatrick Venture 95d2037c6aSPatrick Venture return count; 96d2037c6aSPatrick Venture } 97d2037c6aSPatrick Venture 98*bb90d4fdSPatrick Venture VersionTuple Handler::getCpldVersion(unsigned int id) const 99*bb90d4fdSPatrick Venture { 100*bb90d4fdSPatrick Venture std::ostringstream opath; 101*bb90d4fdSPatrick Venture opath << "/run/cpld" << id << ".version"; 102*bb90d4fdSPatrick Venture // Check for file 103*bb90d4fdSPatrick Venture 104*bb90d4fdSPatrick Venture std::error_code ec; 105*bb90d4fdSPatrick Venture if (!fs::exists(opath.str(), ec)) 106*bb90d4fdSPatrick Venture { 107*bb90d4fdSPatrick Venture std::fprintf(stderr, "Path: '%s' doesn't exist.\n", 108*bb90d4fdSPatrick Venture opath.str().c_str()); 109*bb90d4fdSPatrick Venture throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST); 110*bb90d4fdSPatrick Venture } 111*bb90d4fdSPatrick Venture // We're uninterested in the state of ec. 112*bb90d4fdSPatrick Venture 113*bb90d4fdSPatrick Venture // If file exists, read. 114*bb90d4fdSPatrick Venture std::ifstream ifs; 115*bb90d4fdSPatrick Venture ifs.exceptions(std::ifstream::failbit); 116*bb90d4fdSPatrick Venture std::string value; 117*bb90d4fdSPatrick Venture try 118*bb90d4fdSPatrick Venture { 119*bb90d4fdSPatrick Venture ifs.open(opath.str()); 120*bb90d4fdSPatrick Venture ifs >> value; 121*bb90d4fdSPatrick Venture } 122*bb90d4fdSPatrick Venture catch (std::ios_base::failure& fail) 123*bb90d4fdSPatrick Venture { 124*bb90d4fdSPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 125*bb90d4fdSPatrick Venture } 126*bb90d4fdSPatrick Venture 127*bb90d4fdSPatrick Venture // If value parses as expected, return version. 128*bb90d4fdSPatrick Venture VersionTuple version = std::make_tuple(0, 0, 0, 0); 129*bb90d4fdSPatrick Venture 130*bb90d4fdSPatrick Venture int num_fields = 131*bb90d4fdSPatrick Venture std::sscanf(value.c_str(), "%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8, 132*bb90d4fdSPatrick Venture &std::get<0>(version), &std::get<1>(version), 133*bb90d4fdSPatrick Venture &std::get<2>(version), &std::get<3>(version)); 134*bb90d4fdSPatrick Venture if (num_fields == 0) 135*bb90d4fdSPatrick Venture { 136*bb90d4fdSPatrick Venture std::fprintf(stderr, "Invalid version.\n"); 137*bb90d4fdSPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 138*bb90d4fdSPatrick Venture } 139*bb90d4fdSPatrick Venture 140*bb90d4fdSPatrick Venture return version; 141*bb90d4fdSPatrick Venture } 142*bb90d4fdSPatrick Venture 143f085d91dSPatrick Venture Handler handlerImpl; 144f085d91dSPatrick Venture 145f085d91dSPatrick Venture } // namespace ipmi 146f085d91dSPatrick Venture } // namespace google 147