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