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