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