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