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