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 {
setupUnixSocket(const std::string & socketInterface)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
writeToUnixSocket(const int sock,const char * buf,const uint64_t blockSize)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
checkIfIBMFru(const std::string & objPath)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
findPortObjects(const std::string & adapterObjPath)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