1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
8 #include <sys/socket.h>
16 #include "mlx5_utils.h"
19 * Initialise the socket to communicate with the secondary process
22 * Pointer to private structure.
25 * 0 on success, errno value on failure.
28 priv_socket_init(struct priv *priv)
30 struct sockaddr_un sun = {
31 .sun_family = AF_UNIX,
35 struct stat file_stat;
38 * Initialise the socket to communicate with the secondary
41 ret = socket(AF_UNIX, SOCK_STREAM, 0);
43 WARN("secondary process not supported: %s", strerror(errno));
46 priv->primary_socket = ret;
47 flags = fcntl(priv->primary_socket, F_GETFL, 0);
50 ret = fcntl(priv->primary_socket, F_SETFL, flags | O_NONBLOCK);
53 snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d",
54 MLX5_DRIVER_NAME, priv->primary_socket);
55 ret = stat(sun.sun_path, &file_stat);
57 claim_zero(remove(sun.sun_path));
58 ret = bind(priv->primary_socket, (const struct sockaddr *)&sun,
61 WARN("cannot bind socket, secondary process not supported: %s",
65 ret = listen(priv->primary_socket, 0);
67 WARN("Secondary process not supported: %s", strerror(errno));
74 claim_zero(close(priv->primary_socket));
75 priv->primary_socket = 0;
80 * Un-Initialise the socket to communicate with the secondary process
83 * Pointer to private structure.
86 * 0 on success, errno value on failure.
89 priv_socket_uninit(struct priv *priv)
91 MKSTR(path, "/var/tmp/%s_%d", MLX5_DRIVER_NAME, priv->primary_socket);
92 claim_zero(close(priv->primary_socket));
93 priv->primary_socket = 0;
94 claim_zero(remove(path));
99 * Handle socket interrupts.
102 * Pointer to private structure.
105 priv_socket_handle(struct priv *priv)
109 struct cmsghdr *cmsg = NULL;
110 struct ucred *cred = NULL;
111 char buf[CMSG_SPACE(sizeof(struct ucred))] = { 0 };
112 char vbuf[1024] = { 0 };
115 .iov_len = sizeof(*vbuf),
117 struct msghdr msg = {
121 .msg_controllen = sizeof(buf),
125 /* Accept the connection from the client. */
126 conn_sock = accept(priv->primary_socket, NULL, NULL);
128 WARN("connection failed: %s", strerror(errno));
131 ret = setsockopt(conn_sock, SOL_SOCKET, SO_PASSCRED, &(int){1},
134 WARN("cannot change socket options");
137 ret = recvmsg(conn_sock, &msg, MSG_WAITALL);
139 WARN("received an empty message: %s", strerror(errno));
142 /* Expect to receive credentials only. */
143 cmsg = CMSG_FIRSTHDR(&msg);
148 if ((cmsg->cmsg_type == SCM_CREDENTIALS) &&
149 (cmsg->cmsg_len >= sizeof(*cred))) {
150 cred = (struct ucred *)CMSG_DATA(cmsg);
151 assert(cred != NULL);
153 cmsg = CMSG_NXTHDR(&msg, cmsg);
155 WARN("Message wrongly formatted");
158 /* Make sure all the ancillary data was received and valid. */
159 if ((cred == NULL) || (cred->uid != getuid()) ||
160 (cred->gid != getgid())) {
161 WARN("wrong credentials");
164 /* Set-up the ancillary data. */
165 cmsg = CMSG_FIRSTHDR(&msg);
166 assert(cmsg != NULL);
167 cmsg->cmsg_level = SOL_SOCKET;
168 cmsg->cmsg_type = SCM_RIGHTS;
169 cmsg->cmsg_len = CMSG_LEN(sizeof(priv->ctx->cmd_fd));
170 fd = (int *)CMSG_DATA(cmsg);
171 *fd = priv->ctx->cmd_fd;
172 ret = sendmsg(conn_sock, &msg, 0);
174 WARN("cannot send response");
180 * Connect to the primary process.
183 * Pointer to private structure.
186 * fd on success, negative errno value on failure.
189 priv_socket_connect(struct priv *priv)
191 struct sockaddr_un sun = {
192 .sun_family = AF_UNIX,
198 char buf[CMSG_SPACE(sizeof(*cred))] = { 0 };
199 char vbuf[1024] = { 0 };
202 .iov_len = sizeof(*vbuf),
204 struct msghdr msg = {
206 .msg_controllen = sizeof(buf),
210 struct cmsghdr *cmsg;
212 ret = socket(AF_UNIX, SOCK_STREAM, 0);
214 WARN("cannot connect to primary");
218 snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d",
219 MLX5_DRIVER_NAME, priv->primary_socket);
220 ret = connect(socket_fd, (const struct sockaddr *)&sun, sizeof(sun));
222 WARN("cannot connect to primary");
225 cmsg = CMSG_FIRSTHDR(&msg);
227 DEBUG("cannot get first message");
230 cmsg->cmsg_level = SOL_SOCKET;
231 cmsg->cmsg_type = SCM_CREDENTIALS;
232 cmsg->cmsg_len = CMSG_LEN(sizeof(*cred));
233 cred = (struct ucred *)CMSG_DATA(cmsg);
235 DEBUG("no credentials received");
238 cred->pid = getpid();
239 cred->uid = getuid();
240 cred->gid = getgid();
241 ret = sendmsg(socket_fd, &msg, MSG_DONTWAIT);
243 WARN("cannot send credentials to primary: %s",
247 ret = recvmsg(socket_fd, &msg, MSG_WAITALL);
249 WARN("no message from primary: %s", strerror(errno));
252 cmsg = CMSG_FIRSTHDR(&msg);
254 WARN("No file descriptor received");
257 fd = (int *)CMSG_DATA(cmsg);
259 WARN("no file descriptor received: %s", strerror(errno));