blob: 42690bef1b6b2721a0b5dfb66c24110073687087 [file] [log] [blame]
Jeremy Kerr9326d772016-03-17 17:15:02 +08001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jeremy Kerr2bd05182016-03-10 16:59:43 +080016
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080017#define _GNU_SOURCE
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080018
19#include <assert.h>
Jeremy Kerr2bd05182016-03-10 16:59:43 +080020#include <err.h>
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080021#include <errno.h>
Jeremy Kerr2bd05182016-03-10 16:59:43 +080022#include <stdbool.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <termios.h>
27#include <unistd.h>
28#include <endian.h>
29
30#include <sys/socket.h>
31#include <sys/un.h>
Jonathan Domancc075302023-03-31 10:20:48 -070032#include <systemd/sd-daemon.h>
Jeremy Kerr2bd05182016-03-10 16:59:43 +080033
34#include "console-server.h"
35
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -080036#define SOCKET_HANDLER_PKT_SIZE 512
37/* Set poll() timeout to 4000 uS, or 4 mS */
38#define SOCKET_HANDLER_PKT_US_TIMEOUT 4000
39
Jeremy Kerr2bd05182016-03-10 16:59:43 +080040struct client {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080041 struct socket_handler *sh;
42 struct poller *poller;
43 struct ringbuffer_consumer *rbc;
44 int fd;
Jeremy Kerr6b1fed22017-02-07 21:40:38 +080045 bool blocked;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080046};
47
48struct socket_handler {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080049 struct handler handler;
50 struct console *console;
51 struct poller *poller;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080052 int sd;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080053
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080054 struct client **clients;
55 int n_clients;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080056};
57
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -080058static struct timeval const socket_handler_timeout = {
59 .tv_sec = 0,
60 .tv_usec = SOCKET_HANDLER_PKT_US_TIMEOUT
61};
62
Jeremy Kerr2bd05182016-03-10 16:59:43 +080063static struct socket_handler *to_socket_handler(struct handler *handler)
64{
65 return container_of(handler, struct socket_handler, handler);
66}
67
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080068static void client_close(struct client *client)
Jeremy Kerr2bd05182016-03-10 16:59:43 +080069{
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080070 struct socket_handler *sh = client->sh;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080071 int idx;
72
73 close(client->fd);
74 if (client->poller)
Jeremy Kerr55c97122017-02-07 17:06:46 +080075 console_poller_unregister(sh->console, client->poller);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080076
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080077 if (client->rbc)
78 ringbuffer_consumer_unregister(client->rbc);
79
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080080 for (idx = 0; idx < sh->n_clients; idx++)
81 if (sh->clients[idx] == client)
82 break;
83
84 assert(idx < sh->n_clients);
85
86 free(client);
87 client = NULL;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080088
89 sh->n_clients--;
90 memmove(&sh->clients[idx], &sh->clients[idx+1],
91 sizeof(*sh->clients) * (sh->n_clients - idx));
Joel Stanleyfbff1c62016-03-17 20:32:24 +103092 sh->clients = realloc(sh->clients,
93 sizeof(*sh->clients) * sh->n_clients);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080094}
95
Jeremy Kerr6b1fed22017-02-07 21:40:38 +080096static void client_set_blocked(struct client *client, bool blocked)
Jeremy Kerr848fc872017-01-17 13:50:05 +080097{
Jeremy Kerr6b1fed22017-02-07 21:40:38 +080098 int events;
99
100 if (client->blocked == blocked)
101 return;
102
103 client->blocked = blocked;
104
105 events = POLLIN;
106 if (client->blocked)
107 events |= POLLOUT;
108
109 console_poller_set_events(client->sh->console, client->poller, events);
110}
111
112static ssize_t send_all(struct client *client, void *buf,
113 size_t len, bool block)
114{
115 int fd, rc, flags;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800116 size_t pos;
117
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800118 fd = client->fd;
119
Jeremy Kerr848fc872017-01-17 13:50:05 +0800120 flags = MSG_NOSIGNAL;
121 if (!block)
122 flags |= MSG_DONTWAIT;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800123
124 for (pos = 0; pos < len; pos += rc) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800125 rc = send(fd, buf + pos, len - pos, flags);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800126 if (rc < 0) {
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800127 if (!block && (errno == EAGAIN ||
128 errno == EWOULDBLOCK)) {
129 client_set_blocked(client, true);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800130 break;
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800131 }
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800132
133 if (errno == EINTR)
134 continue;
135
136 return -1;
137 }
138 if (rc == 0)
139 return -1;
140 }
141
142 return pos;
143}
144
Jeremy Kerr848fc872017-01-17 13:50:05 +0800145/* Drain the queue to the socket and update the queue buffer. If force_len is
146 * set, send at least that many bytes from the queue, possibly while blocking
147 */
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800148static int client_drain_queue(struct client *client, size_t force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800149{
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800150 uint8_t *buf;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800151 ssize_t wlen;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800152 size_t len, total_len;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800153 bool block;
154
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800155 total_len = 0;
156 wlen = 0;
157 block = !!force_len;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800158
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800159 /* if we're already blocked, no need for the write */
160 if (!block && client->blocked)
161 return 0;
162
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800163 for (;;) {
164 len = ringbuffer_dequeue_peek(client->rbc, total_len, &buf);
165 if (!len)
166 break;
167
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800168 wlen = send_all(client, buf, len, block);
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800169 if (wlen <= 0)
170 break;
171
172 total_len += wlen;
173
174 if (force_len && total_len >= force_len)
175 break;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800176 }
177
Jeremy Kerr848fc872017-01-17 13:50:05 +0800178 if (wlen < 0)
179 return -1;
180
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800181 if (force_len && total_len < force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800182 return -1;
183
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800184 ringbuffer_dequeue_commit(client->rbc, total_len);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800185 return 0;
186}
187
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800188static enum ringbuffer_poll_ret client_ringbuffer_poll(void *arg,
189 size_t force_len)
190{
191 struct client *client = arg;
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800192 int rc, len;
193
194 len = ringbuffer_len(client->rbc);
195 if (!force_len && (len < SOCKET_HANDLER_PKT_SIZE)) {
196 /* Do nothing until many small requests have accumulated, or
197 * the UART is idle for awhile (as determined by the timeout
198 * value supplied to the poll function call in console_server.c. */
199 console_poller_set_timeout(client->sh->console, client->poller,
200 &socket_handler_timeout);
201 return RINGBUFFER_POLL_OK;
202 }
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800203
204 rc = client_drain_queue(client, force_len);
205 if (rc) {
206 client->rbc = NULL;
207 client_close(client);
208 return RINGBUFFER_POLL_REMOVE;
209 }
210
211 return RINGBUFFER_POLL_OK;
212}
213
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800214static enum poller_ret client_timeout(struct handler *handler, void *data)
215{
216 struct client *client = data;
217 int rc = 0;
218
219 if (client->blocked) {
220 /* nothing to do here, we'll call client_drain_queue when
221 * we become unblocked */
222 return POLLER_OK;
223 }
224
225 rc = client_drain_queue(client, 0);
226 if (rc) {
227 client_close(client);
228 return POLLER_REMOVE;
229 }
230
231 return POLLER_OK;
232}
233
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800234static enum poller_ret client_poll(struct handler *handler,
235 int events, void *data)
236{
237 struct socket_handler *sh = to_socket_handler(handler);
238 struct client *client = data;
239 uint8_t buf[4096];
240 int rc;
241
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800242 if (events & POLLIN) {
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800243 rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800244 if (rc < 0) {
245 if (errno == EAGAIN || errno == EWOULDBLOCK)
246 return POLLER_OK;
247 else
248 goto err_close;
249 }
250 if (rc == 0)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800251 goto err_close;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800252
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800253 console_data_out(sh->console, buf, rc);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800254 }
255
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800256 if (events & POLLOUT) {
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800257 client_set_blocked(client, false);
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800258 rc = client_drain_queue(client, 0);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800259 if (rc)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800260 goto err_close;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800261 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800262
263 return POLLER_OK;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800264
265err_close:
266 client->poller = NULL;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800267 client_close(client);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800268 return POLLER_REMOVE;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800269}
270
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800271static enum poller_ret socket_poll(struct handler *handler,
272 int events, void __attribute__((unused)) *data)
273{
274 struct socket_handler *sh = to_socket_handler(handler);
275 struct client *client;
276 int fd, n;
277
278 if (!(events & POLLIN))
279 return POLLER_OK;
280
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800281 fd = accept(sh->sd, NULL, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800282 if (fd < 0)
283 return POLLER_OK;
284
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800285 client = malloc(sizeof(*client));
286 memset(client, 0, sizeof(*client));
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800287
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800288 client->sh = sh;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800289 client->fd = fd;
Jeremy Kerr55c97122017-02-07 17:06:46 +0800290 client->poller = console_poller_register(sh->console, handler,
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800291 client_poll, client_timeout, client->fd, POLLIN,
292 client);
Jeremy Kerrf733c852017-02-07 18:40:10 +0800293 client->rbc = console_ringbuffer_consumer_register(sh->console,
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800294 client_ringbuffer_poll, client);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800295
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800296 n = sh->n_clients++;
297 sh->clients = realloc(sh->clients,
298 sizeof(*sh->clients) * sh->n_clients);
299 sh->clients[n] = client;
300
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800301 return POLLER_OK;
302
303}
304
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800305static int socket_init(struct handler *handler, struct console *console,
Andrew Jefferyddf2ab72020-02-10 12:36:09 +1030306 struct config *config)
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800307{
308 struct socket_handler *sh = to_socket_handler(handler);
309 struct sockaddr_un addr;
Andrew Jeffery5e7c0782020-02-10 12:12:36 +1030310 size_t addrlen;
311 ssize_t len;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800312 int rc;
313
314 sh->console = console;
315 sh->clients = NULL;
316 sh->n_clients = 0;
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800317
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800318 memset(&addr, 0, sizeof(addr));
319 addr.sun_family = AF_UNIX;
Andrew Jefferyddf2ab72020-02-10 12:36:09 +1030320 len = console_socket_path(&addr, config_get_value(config, "socket-id"));
Andrew Jeffery5e7c0782020-02-10 12:12:36 +1030321 if (len < 0) {
322 if (errno)
323 warn("Failed to configure socket: %s", strerror(errno));
324 else
325 warn("Socket name length exceeds buffer limits");
Jonathan Domancc075302023-03-31 10:20:48 -0700326 return -1;
Andrew Jeffery5e7c0782020-02-10 12:12:36 +1030327 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800328
Jonathan Domancc075302023-03-31 10:20:48 -0700329 /* Try to take a socket from systemd first */
330 if (sd_listen_fds(0) == 1 &&
331 sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1, addr.sun_path, len) > 0) {
332 sh->sd = SD_LISTEN_FDS_START;
333 } else {
334 sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
335 if(sh->sd < 0) {
336 warn("Can't create socket");
337 return -1;
338 }
Andrew Jeffery5e7c0782020-02-10 12:12:36 +1030339
Jonathan Domancc075302023-03-31 10:20:48 -0700340 addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800341
Jonathan Domancc075302023-03-31 10:20:48 -0700342 rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
343 if (rc) {
344 socket_path_t name;
345 console_socket_path_readable(&addr, addrlen, name);
346 warn("Can't bind to socket path %s (terminated at first null)",
347 name);
348 goto cleanup;
349 }
350
351 rc = listen(sh->sd, 1);
352 if (rc) {
353 warn("Can't listen for incoming connections");
354 goto cleanup;
355 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800356 }
357
Jeremy Kerr55c97122017-02-07 17:06:46 +0800358 sh->poller = console_poller_register(console, handler, socket_poll,
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800359 NULL, sh->sd, POLLIN, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800360
361 return 0;
Andrew Jeffery5e7c0782020-02-10 12:12:36 +1030362cleanup:
363 close(sh->sd);
364 return -1;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800365}
366
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800367static void socket_fini(struct handler *handler)
368{
369 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800370
Jeremy Kerrabd8e252017-01-19 15:42:48 +0800371 while (sh->n_clients)
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800372 client_close(sh->clients[0]);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800373
374 if (sh->poller)
Jeremy Kerr55c97122017-02-07 17:06:46 +0800375 console_poller_unregister(sh->console, sh->poller);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800376
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800377 close(sh->sd);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800378}
379
380static struct socket_handler socket_handler = {
381 .handler = {
382 .name = "socket",
383 .init = socket_init,
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800384 .fini = socket_fini,
385 },
386};
387
Jeremy Kerr55c97122017-02-07 17:06:46 +0800388console_handler_register(&socket_handler.handler);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800389