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