1 #include "utils.hpp" 2 3 #include "common/utils.hpp" 4 5 #include <libpldm/base.h> 6 #include <sys/socket.h> 7 #include <sys/types.h> 8 #include <sys/un.h> 9 #include <unistd.h> 10 11 #include <phosphor-logging/lg2.hpp> 12 #include <xyz/openbmc_project/Inventory/Decorator/Asset/client.hpp> 13 #include <xyz/openbmc_project/Inventory/Item/Connector/client.hpp> 14 #include <xyz/openbmc_project/ObjectMapper/client.hpp> 15 16 PHOSPHOR_LOG2_USING; 17 18 using namespace pldm::utils; 19 20 namespace pldm 21 { 22 namespace responder 23 { 24 namespace utils 25 { 26 int setupUnixSocket(const std::string& socketInterface) 27 { 28 int sock; 29 struct sockaddr_un addr; 30 memset(&addr, 0, sizeof(addr)); 31 addr.sun_family = AF_UNIX; 32 size_t interfaceLength = strnlen(socketInterface.c_str(), 33 sizeof(addr.sun_path)); 34 if (interfaceLength == sizeof(addr.sun_path)) 35 { 36 error("Setup unix socket path '{PATH}' is too long '{LENGTH}'", "PATH", 37 socketInterface, "LENGTH", interfaceLength); 38 return -1; 39 } 40 41 strncpy(addr.sun_path, socketInterface.c_str(), sizeof(addr.sun_path) - 1); 42 43 if ((sock = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) 44 { 45 error("Failed to open unix socket"); 46 return -1; 47 } 48 49 if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) 50 { 51 error("Failed to bind unix socket, error number - {ERROR_NUM}", 52 "ERROR_NUM", errno); 53 close(sock); 54 return -1; 55 } 56 57 if (listen(sock, 1) == -1) 58 { 59 error("Failed listen() call while setting up unix socket"); 60 close(sock); 61 return -1; 62 } 63 64 fd_set rfd; 65 struct timeval tv; 66 tv.tv_sec = 1; 67 tv.tv_usec = 0; 68 69 FD_ZERO(&rfd); 70 FD_SET(sock, &rfd); 71 int nfd = sock + 1; 72 int fd = -1; 73 74 int retval = select(nfd, &rfd, NULL, NULL, &tv); 75 if (retval < 0) 76 { 77 error( 78 "Failed select() call while setting up unix socket, error number - {ERROR_NUM}", 79 "ERROR_NUM", errno); 80 close(sock); 81 return -1; 82 } 83 84 if ((retval > 0) && (FD_ISSET(sock, &rfd))) 85 { 86 fd = accept(sock, NULL, NULL); 87 if (fd < 0) 88 { 89 error( 90 "Failed accept() call while setting up unix socket, error number - {ERROR_NUM}", 91 "ERROR_NUM", errno); 92 close(sock); 93 return -1; 94 } 95 close(sock); 96 } 97 return fd; 98 } 99 100 int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize) 101 { 102 uint64_t i; 103 int nwrite = 0; 104 105 for (i = 0; i < blockSize; i = i + nwrite) 106 { 107 fd_set wfd; 108 struct timeval tv; 109 tv.tv_sec = 1; 110 tv.tv_usec = 0; 111 112 FD_ZERO(&wfd); 113 FD_SET(sock, &wfd); 114 int nfd = sock + 1; 115 116 int retval = select(nfd, NULL, &wfd, NULL, &tv); 117 if (retval < 0) 118 { 119 error( 120 "Failed to write to unix socket select, error number - {ERROR_NUM}", 121 "ERROR_NUM", errno); 122 close(sock); 123 return -1; 124 } 125 if (retval == 0) 126 { 127 nwrite = 0; 128 continue; 129 } 130 if ((retval > 0) && (FD_ISSET(sock, &wfd))) 131 { 132 nwrite = write(sock, buf + i, blockSize - i); 133 if (nwrite < 0) 134 { 135 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) 136 { 137 error( 138 "Failed to write to unix socket, error number - {ERROR_NUM}", 139 "ERROR_NUM", errno); 140 nwrite = 0; 141 continue; 142 } 143 error( 144 "Failed to write to unix socket, error number - {ERROR_NUM}", 145 "ERROR_NUM", errno); 146 close(sock); 147 return -1; 148 } 149 } 150 else 151 { 152 nwrite = 0; 153 } 154 } 155 return 0; 156 } 157 158 bool checkIfIBMFru(const std::string& objPath) 159 { 160 using DecoratorAsset = 161 sdbusplus::client::xyz::openbmc_project::inventory::decorator::Asset<>; 162 163 try 164 { 165 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 166 objPath.c_str(), "Model", DecoratorAsset::interface); 167 const auto& model = std::get<std::string>(propVal); 168 if (!model.empty()) 169 { 170 return true; 171 } 172 } 173 catch (const std::exception&) 174 { 175 return false; 176 } 177 return false; 178 } 179 180 std::vector<std::string> findPortObjects(const std::string& adapterObjPath) 181 { 182 using ItemConnector = 183 sdbusplus::client::xyz::openbmc_project::inventory::item::Connector<>; 184 185 std::vector<std::string> portObjects; 186 try 187 { 188 portObjects = pldm::utils::DBusHandler().getSubTreePaths( 189 adapterObjPath, 0, 190 std::vector<std::string>({ItemConnector::interface})); 191 } 192 catch (const std::exception& e) 193 { 194 error("No ports under adapter '{ADAPTER_OBJ_PATH}' - {ERROR}.", 195 "ADAPTER_OBJ_PATH", adapterObjPath.c_str(), "ERROR", e); 196 } 197 198 return portObjects; 199 } 200 } // namespace utils 201 } // namespace responder 202 } // namespace pldm 203