blob: c41211ece7c69a190c554decd7d70600944f802e [file] [log] [blame]
Ravi Tejace1c96f2020-10-05 23:13:01 -05001#include "utils.hpp"
2
George Liuc453e162022-12-21 17:16:23 +08003#include <libpldm/base.h>
Ravi Tejace1c96f2020-10-05 23:13:01 -05004#include <sys/socket.h>
5#include <sys/types.h>
6#include <sys/un.h>
7#include <unistd.h>
8
Riya Dixit49cfb132023-03-02 04:26:53 -06009#include <phosphor-logging/lg2.hpp>
10
Ravi Tejace1c96f2020-10-05 23:13:01 -050011#include <iostream>
12
Riya Dixit49cfb132023-03-02 04:26:53 -060013PHOSPHOR_LOG2_USING;
14
Ravi Tejace1c96f2020-10-05 23:13:01 -050015namespace pldm
16{
17namespace responder
18{
19namespace utils
20{
Ravi Tejace1c96f2020-10-05 23:13:01 -050021int setupUnixSocket(const std::string& socketInterface)
22{
23 int sock;
24 struct sockaddr_un addr;
25 memset(&addr, 0, sizeof(addr));
26 addr.sun_family = AF_UNIX;
27 if (strnlen(socketInterface.c_str(), sizeof(addr.sun_path)) ==
28 sizeof(addr.sun_path))
29 {
Riya Dixit49cfb132023-03-02 04:26:53 -060030 error("setupUnixSocket: UNIX socket path too long");
Ravi Tejace1c96f2020-10-05 23:13:01 -050031 return -1;
32 }
33
34 strncpy(addr.sun_path, socketInterface.c_str(), sizeof(addr.sun_path) - 1);
35
36 if ((sock = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
37 {
Riya Dixit49cfb132023-03-02 04:26:53 -060038 error("setupUnixSocket: socket() call failed");
Ravi Tejace1c96f2020-10-05 23:13:01 -050039 return -1;
40 }
41
42 if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
43 {
Riya Dixit49cfb132023-03-02 04:26:53 -060044 error("setupUnixSocket: bind() call failed with errno {ERR}", "ERR",
45 errno);
Ravi Tejace1c96f2020-10-05 23:13:01 -050046 close(sock);
47 return -1;
48 }
49
50 if (listen(sock, 1) == -1)
51 {
Riya Dixit49cfb132023-03-02 04:26:53 -060052 error("setupUnixSocket: listen() call failed");
Ravi Tejace1c96f2020-10-05 23:13:01 -050053 close(sock);
54 return -1;
55 }
56
57 fd_set rfd;
58 struct timeval tv;
59 tv.tv_sec = 1;
60 tv.tv_usec = 0;
61
62 FD_ZERO(&rfd);
63 FD_SET(sock, &rfd);
64 int nfd = sock + 1;
Andrew Geisslerefbb5942020-12-15 10:12:30 -060065 int fd = -1;
Ravi Tejace1c96f2020-10-05 23:13:01 -050066
67 int retval = select(nfd, &rfd, NULL, NULL, &tv);
68 if (retval < 0)
69 {
Riya Dixit49cfb132023-03-02 04:26:53 -060070 error("setupUnixSocket: select call failed {ERR}", "ERR", errno);
Ravi Tejace1c96f2020-10-05 23:13:01 -050071 close(sock);
72 return -1;
73 }
74
75 if ((retval > 0) && (FD_ISSET(sock, &rfd)))
76 {
77 fd = accept(sock, NULL, NULL);
78 if (fd < 0)
79 {
Riya Dixit49cfb132023-03-02 04:26:53 -060080 error("setupUnixSocket: accept() call failed {ERR}", "ERR", errno);
Ravi Tejace1c96f2020-10-05 23:13:01 -050081 close(sock);
82 return -1;
83 }
84 close(sock);
85 }
86 return fd;
87}
88
89int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize)
90{
91 uint64_t i;
92 int nwrite = 0;
93
94 for (i = 0; i < blockSize; i = i + nwrite)
95 {
Ravi Tejace1c96f2020-10-05 23:13:01 -050096 fd_set wfd;
97 struct timeval tv;
98 tv.tv_sec = 1;
99 tv.tv_usec = 0;
100
101 FD_ZERO(&wfd);
102 FD_SET(sock, &wfd);
103 int nfd = sock + 1;
104
105 int retval = select(nfd, NULL, &wfd, NULL, &tv);
106 if (retval < 0)
107 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600108 error("writeToUnixSocket: select call failed {ERR}", "ERR", errno);
Ravi Tejace1c96f2020-10-05 23:13:01 -0500109 close(sock);
110 return -1;
111 }
112 if (retval == 0)
113 {
114 nwrite = 0;
115 continue;
116 }
117 if ((retval > 0) && (FD_ISSET(sock, &wfd)))
118 {
119 nwrite = write(sock, buf + i, blockSize - i);
120 if (nwrite < 0)
121 {
122 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
123 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600124 error(
125 "writeToUnixSocket: Write call failed with EAGAIN or EWOULDBLOCK or EINTR");
Ravi Tejace1c96f2020-10-05 23:13:01 -0500126 nwrite = 0;
127 continue;
128 }
Riya Dixit49cfb132023-03-02 04:26:53 -0600129 error("writeToUnixSocket: Failed to write {ERR}", "ERR", errno);
Ravi Tejace1c96f2020-10-05 23:13:01 -0500130 close(sock);
131 return -1;
132 }
133 }
134 else
135 {
136 nwrite = 0;
137 }
138 }
139 return 0;
140}
141
142} // namespace utils
143} // namespace responder
144} // namespace pldm