xref: /openbmc/obmc-console/socket-handler.c (revision 7851a396511b623aca735d607382b93494c332a4)
1 /**
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  */
16 
17 #include <assert.h>
18 #include <err.h>
19 #include <errno.h>
20 #include <limits.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <termios.h>
26 #include <unistd.h>
27 #include <endian.h>
28 
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <systemd/sd-daemon.h>
32 
33 #include "console-server.h"
34 
35 #define SOCKET_HANDLER_PKT_SIZE 512
36 /* Set poll() timeout to 4000 uS, or 4 mS */
37 #define SOCKET_HANDLER_PKT_US_TIMEOUT 4000
38 
39 struct client {
40 	struct socket_handler *sh;
41 	struct poller *poller;
42 	struct ringbuffer_consumer *rbc;
43 	int fd;
44 	bool blocked;
45 };
46 
47 struct socket_handler {
48 	struct handler handler;
49 	struct console *console;
50 	struct poller *poller;
51 	int sd;
52 
53 	struct client **clients;
54 	int n_clients;
55 };
56 
57 static struct timeval const socket_handler_timeout = {
58 	.tv_sec = 0,
59 	.tv_usec = SOCKET_HANDLER_PKT_US_TIMEOUT
60 };
61 
62 static struct socket_handler *to_socket_handler(struct handler *handler)
63 {
64 	return container_of(handler, struct socket_handler, handler);
65 }
66 
67 static void client_close(struct client *client)
68 {
69 	struct socket_handler *sh = client->sh;
70 	int idx;
71 
72 	close(client->fd);
73 	if (client->poller) {
74 		console_poller_unregister(sh->console, client->poller);
75 	}
76 
77 	if (client->rbc) {
78 		ringbuffer_consumer_unregister(client->rbc);
79 	}
80 
81 	for (idx = 0; idx < sh->n_clients; idx++) {
82 		if (sh->clients[idx] == client) {
83 			break;
84 		}
85 	}
86 
87 	assert(idx < sh->n_clients);
88 
89 	free(client);
90 	client = NULL;
91 
92 	sh->n_clients--;
93 	/*
94 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
95 	 * pointer type.
96 	 */
97 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
98 	memmove(&sh->clients[idx], &sh->clients[idx + 1],
99 		sizeof(*sh->clients) * (sh->n_clients - idx));
100 	if (sh->n_clients == 0) {
101 		free(sh->clients);
102 		sh->clients = NULL;
103 	} else {
104 		sh->clients = reallocarray(sh->clients, sh->n_clients,
105 					   sizeof(*sh->clients));
106 	}
107 	/* NOLINTEND(bugprone-sizeof-expression) */
108 }
109 
110 static void client_set_blocked(struct client *client, bool blocked)
111 {
112 	int events;
113 
114 	if (client->blocked == blocked) {
115 		return;
116 	}
117 
118 	client->blocked = blocked;
119 
120 	events = POLLIN;
121 	if (client->blocked) {
122 		events |= POLLOUT;
123 	}
124 
125 	console_poller_set_events(client->sh->console, client->poller, events);
126 }
127 
128 static ssize_t send_all(struct client *client, void *buf, size_t len,
129 			bool block)
130 {
131 	int fd;
132 	int flags;
133 	ssize_t rc;
134 	size_t pos;
135 
136 	if (len > SSIZE_MAX) {
137 		return -EINVAL;
138 	}
139 
140 	fd = client->fd;
141 
142 	flags = MSG_NOSIGNAL;
143 	if (!block) {
144 		flags |= MSG_DONTWAIT;
145 	}
146 
147 	for (pos = 0; pos < len; pos += rc) {
148 		rc = send(fd, (char *)buf + pos, len - pos, flags);
149 		if (rc < 0) {
150 			if (!block &&
151 			    (errno == EAGAIN || errno == EWOULDBLOCK)) {
152 				client_set_blocked(client, true);
153 				break;
154 			}
155 
156 			if (errno == EINTR) {
157 				continue;
158 			}
159 
160 			return -1;
161 		}
162 		if (rc == 0) {
163 			return -1;
164 		}
165 	}
166 
167 	return (ssize_t)pos;
168 }
169 
170 /* Drain the queue to the socket and update the queue buffer. If force_len is
171  * set, send at least that many bytes from the queue, possibly while blocking
172  */
173 static int client_drain_queue(struct client *client, size_t force_len)
174 {
175 	uint8_t *buf;
176 	ssize_t wlen;
177 	size_t len;
178 	size_t total_len;
179 	bool block;
180 
181 	total_len = 0;
182 	wlen = 0;
183 	block = !!force_len;
184 
185 	/* if we're already blocked, no need for the write */
186 	if (!block && client->blocked) {
187 		return 0;
188 	}
189 
190 	for (;;) {
191 		len = ringbuffer_dequeue_peek(client->rbc, total_len, &buf);
192 		if (!len) {
193 			break;
194 		}
195 
196 		wlen = send_all(client, buf, len, block);
197 		if (wlen <= 0) {
198 			break;
199 		}
200 
201 		total_len += wlen;
202 
203 		if (force_len && total_len >= force_len) {
204 			break;
205 		}
206 	}
207 
208 	if (wlen < 0) {
209 		return -1;
210 	}
211 
212 	if (force_len && total_len < force_len) {
213 		return -1;
214 	}
215 
216 	ringbuffer_dequeue_commit(client->rbc, total_len);
217 	return 0;
218 }
219 
220 static enum ringbuffer_poll_ret client_ringbuffer_poll(void *arg,
221 						       size_t force_len)
222 {
223 	struct client *client = arg;
224 	size_t len;
225 	int rc;
226 
227 	len = ringbuffer_len(client->rbc);
228 	if (!force_len && (len < SOCKET_HANDLER_PKT_SIZE)) {
229 		/* Do nothing until many small requests have accumulated, or
230 		 * the UART is idle for awhile (as determined by the timeout
231 		 * value supplied to the poll function call in console_server.c. */
232 		console_poller_set_timeout(client->sh->console, client->poller,
233 					   &socket_handler_timeout);
234 		return RINGBUFFER_POLL_OK;
235 	}
236 
237 	rc = client_drain_queue(client, force_len);
238 	if (rc) {
239 		client->rbc = NULL;
240 		client_close(client);
241 		return RINGBUFFER_POLL_REMOVE;
242 	}
243 
244 	return RINGBUFFER_POLL_OK;
245 }
246 
247 static enum poller_ret
248 client_timeout(struct handler *handler __attribute__((unused)), void *data)
249 {
250 	struct client *client = data;
251 	int rc = 0;
252 
253 	if (client->blocked) {
254 		/* nothing to do here, we'll call client_drain_queue when
255 		 * we become unblocked */
256 		return POLLER_OK;
257 	}
258 
259 	rc = client_drain_queue(client, 0);
260 	if (rc) {
261 		client_close(client);
262 		return POLLER_REMOVE;
263 	}
264 
265 	return POLLER_OK;
266 }
267 
268 static enum poller_ret client_poll(struct handler *handler, int events,
269 				   void *data)
270 {
271 	struct socket_handler *sh = to_socket_handler(handler);
272 	struct client *client = data;
273 	uint8_t buf[4096];
274 	ssize_t rc;
275 
276 	if (events & POLLIN) {
277 		rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
278 		if (rc < 0) {
279 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
280 				return POLLER_OK;
281 			}
282 			goto err_close;
283 		}
284 		if (rc == 0) {
285 			goto err_close;
286 		}
287 
288 		console_data_out(sh->console, buf, rc);
289 	}
290 
291 	if (events & POLLOUT) {
292 		client_set_blocked(client, false);
293 		rc = client_drain_queue(client, 0);
294 		if (rc) {
295 			goto err_close;
296 		}
297 	}
298 
299 	return POLLER_OK;
300 
301 err_close:
302 	client->poller = NULL;
303 	client_close(client);
304 	return POLLER_REMOVE;
305 }
306 
307 static enum poller_ret socket_poll(struct handler *handler, int events,
308 				   void __attribute__((unused)) * data)
309 {
310 	struct socket_handler *sh = to_socket_handler(handler);
311 	struct client *client;
312 	int fd;
313 	int n;
314 
315 	if (!(events & POLLIN)) {
316 		return POLLER_OK;
317 	}
318 
319 	fd = accept(sh->sd, NULL, NULL);
320 	if (fd < 0) {
321 		return POLLER_OK;
322 	}
323 
324 	client = malloc(sizeof(*client));
325 	memset(client, 0, sizeof(*client));
326 
327 	client->sh = sh;
328 	client->fd = fd;
329 	client->poller = console_poller_register(sh->console, handler,
330 						 client_poll, client_timeout,
331 						 client->fd, POLLIN, client);
332 	client->rbc = console_ringbuffer_consumer_register(
333 		sh->console, client_ringbuffer_poll, client);
334 
335 	n = sh->n_clients++;
336 	/*
337 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
338 	 * pointer type.
339 	 */
340 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
341 	sh->clients =
342 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
343 	/* NOLINTEND(bugprone-sizeof-expression) */
344 	sh->clients[n] = client;
345 
346 	return POLLER_OK;
347 }
348 
349 /* Create socket pair and register one end as poller/consumer and return
350  * the other end to the caller.
351  * Return file descriptor on success and negative value on error.
352  */
353 int dbus_create_socket_consumer(struct console *console)
354 {
355 	struct socket_handler *sh = NULL;
356 	struct client *client;
357 	int fds[2];
358 	int i;
359 	int rc = -1;
360 	int n;
361 
362 	for (i = 0; i < console->n_handlers; i++) {
363 		if (strcmp(console->handlers[i]->type->name, "socket") == 0) {
364 			sh = to_socket_handler(console->handlers[i]);
365 			break;
366 		}
367 	}
368 
369 	if (!sh) {
370 		return -ENOSYS;
371 	}
372 
373 	/* Create a socketpair */
374 	rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
375 	if (rc < 0) {
376 		warn("Failed to create socket pair");
377 		return -errno;
378 	}
379 
380 	client = malloc(sizeof(*client));
381 	if (client == NULL) {
382 		warnx("Failed to allocate client structure.");
383 		rc = -ENOMEM;
384 		goto close_fds;
385 	}
386 	memset(client, 0, sizeof(*client));
387 
388 	client->sh = sh;
389 	client->fd = fds[0];
390 	client->poller = console_poller_register(sh->console, &sh->handler,
391 						 client_poll, client_timeout,
392 						 client->fd, POLLIN, client);
393 	client->rbc = console_ringbuffer_consumer_register(
394 		sh->console, client_ringbuffer_poll, client);
395 	if (client->rbc == NULL) {
396 		warnx("Failed to register a consumer.\n");
397 		rc = -ENOMEM;
398 		goto free_client;
399 	}
400 
401 	n = sh->n_clients++;
402 
403 	/*
404 	 * We're managing an array of pointers to aggregates, so don't warn about
405 	 * sizeof() on a pointer type.
406 	 */
407 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
408 	sh->clients =
409 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
410 	/* NOLINTEND(bugprone-sizeof-expression) */
411 	sh->clients[n] = client;
412 
413 	/* Return the second FD to caller. */
414 	return fds[1];
415 
416 free_client:
417 	free(client);
418 close_fds:
419 	close(fds[0]);
420 	close(fds[1]);
421 	return rc;
422 }
423 
424 static struct handler *socket_init(const struct handler_type *type
425 				   __attribute__((unused)),
426 				   struct console *console,
427 				   struct config *config
428 				   __attribute__((unused)))
429 {
430 	struct socket_handler *sh;
431 	struct sockaddr_un addr;
432 	size_t addrlen;
433 	ssize_t len;
434 	int rc;
435 
436 	sh = malloc(sizeof(*sh));
437 	if (!sh) {
438 		return NULL;
439 	}
440 
441 	sh->console = console;
442 	sh->clients = NULL;
443 	sh->n_clients = 0;
444 
445 	memset(&addr, 0, sizeof(addr));
446 	addr.sun_family = AF_UNIX;
447 	len = console_socket_path(addr.sun_path, console->console_id);
448 	if (len < 0) {
449 		if (errno) {
450 			warn("Failed to configure socket: %s", strerror(errno));
451 		} else {
452 			warn("Socket name length exceeds buffer limits");
453 		}
454 		goto err_free;
455 	}
456 
457 	/* Try to take a socket from systemd first */
458 	if (sd_listen_fds(0) == 1 &&
459 	    sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1,
460 			      addr.sun_path, len) > 0) {
461 		sh->sd = SD_LISTEN_FDS_START;
462 	} else {
463 		sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
464 		if (sh->sd < 0) {
465 			warn("Can't create socket");
466 			goto err_free;
467 		}
468 
469 		addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
470 
471 		rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
472 		if (rc) {
473 			socket_path_t name;
474 			console_socket_path_readable(&addr, addrlen, name);
475 			warn("Can't bind to socket path %s (terminated at first null)",
476 			     name);
477 			goto err_close;
478 		}
479 
480 		rc = listen(sh->sd, 1);
481 		if (rc) {
482 			warn("Can't listen for incoming connections");
483 			goto err_close;
484 		}
485 	}
486 
487 	sh->poller = console_poller_register(console, &sh->handler, socket_poll,
488 					     NULL, sh->sd, POLLIN, NULL);
489 
490 	return &sh->handler;
491 
492 err_close:
493 	close(sh->sd);
494 err_free:
495 	free(sh);
496 	return NULL;
497 }
498 
499 static void socket_fini(struct handler *handler)
500 {
501 	struct socket_handler *sh = to_socket_handler(handler);
502 
503 	while (sh->n_clients) {
504 		client_close(sh->clients[0]);
505 	}
506 
507 	if (sh->poller) {
508 		console_poller_unregister(sh->console, sh->poller);
509 	}
510 
511 	close(sh->sd);
512 	free(sh);
513 }
514 
515 static const struct handler_type socket_handler = {
516 	.name = "socket",
517 	.init = socket_init,
518 	.fini = socket_fini,
519 };
520 
521 console_handler_register(&socket_handler);
522