xref: /openbmc/obmc-console/socket-handler.c (revision 375786fc0e8ce34d72bafffb03a28689df94fb62)
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->poller = NULL;
263 		client_close(client);
264 		return POLLER_REMOVE;
265 	}
266 
267 	return POLLER_OK;
268 }
269 
client_poll(struct handler * handler,int events,void * data)270 static enum poller_ret client_poll(struct handler *handler, int events,
271 				   void *data)
272 {
273 	struct socket_handler *sh = to_socket_handler(handler);
274 	struct client *client = data;
275 	uint8_t buf[4096];
276 	ssize_t rc;
277 
278 	if (events & POLLIN) {
279 		rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
280 		if (rc < 0) {
281 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
282 				return POLLER_OK;
283 			}
284 			goto err_close;
285 		}
286 		if (rc == 0) {
287 			goto err_close;
288 		}
289 
290 		console_data_out(sh->console, buf, rc);
291 	}
292 
293 	if (events & POLLOUT) {
294 		client_set_blocked(client, false);
295 		rc = client_drain_queue(client, 0);
296 		if (rc) {
297 			goto err_close;
298 		}
299 	}
300 
301 	return POLLER_OK;
302 
303 err_close:
304 	client->poller = NULL;
305 	client_close(client);
306 	return POLLER_REMOVE;
307 }
308 
socket_poll(struct handler * handler,int events,void * data)309 static enum poller_ret socket_poll(struct handler *handler, int events,
310 				   void __attribute__((unused)) * data)
311 {
312 	struct socket_handler *sh = to_socket_handler(handler);
313 	struct client *client;
314 	int fd;
315 	int n;
316 
317 	if (!(events & POLLIN)) {
318 		return POLLER_OK;
319 	}
320 
321 	fd = accept(sh->sd, NULL, NULL);
322 	if (fd < 0) {
323 		return POLLER_OK;
324 	}
325 
326 	console_mux_activate(sh->console);
327 
328 	client = malloc(sizeof(*client));
329 	memset(client, 0, sizeof(*client));
330 
331 	client->sh = sh;
332 	client->fd = fd;
333 	client->poller = console_poller_register(sh->console, handler,
334 						 client_poll, client_timeout,
335 						 client->fd, POLLIN, client);
336 	client->rbc = console_ringbuffer_consumer_register(
337 		sh->console, client_ringbuffer_poll, client);
338 
339 	n = sh->n_clients++;
340 	/*
341 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
342 	 * pointer type.
343 	 */
344 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
345 	sh->clients =
346 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
347 	/* NOLINTEND(bugprone-sizeof-expression) */
348 	sh->clients[n] = client;
349 
350 	return POLLER_OK;
351 }
352 
353 /* Create socket pair and register one end as poller/consumer and return
354  * the other end to the caller.
355  * Return file descriptor on success and negative value on error.
356  */
dbus_create_socket_consumer(struct console * console)357 int dbus_create_socket_consumer(struct console *console)
358 {
359 	struct socket_handler *sh = NULL;
360 	struct client *client;
361 	int fds[2];
362 	int i;
363 	int rc = -1;
364 	int n;
365 
366 	for (i = 0; i < console->n_handlers; i++) {
367 		if (strcmp(console->handlers[i]->type->name, "socket") == 0) {
368 			sh = to_socket_handler(console->handlers[i]);
369 			break;
370 		}
371 	}
372 
373 	if (!sh) {
374 		return -ENOSYS;
375 	}
376 
377 	/* Create a socketpair */
378 	rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
379 	if (rc < 0) {
380 		warn("Failed to create socket pair");
381 		return -errno;
382 	}
383 
384 	client = malloc(sizeof(*client));
385 	if (client == NULL) {
386 		warnx("Failed to allocate client structure.");
387 		rc = -ENOMEM;
388 		goto close_fds;
389 	}
390 	memset(client, 0, sizeof(*client));
391 
392 	client->sh = sh;
393 	client->fd = fds[0];
394 	client->poller = console_poller_register(sh->console, &sh->handler,
395 						 client_poll, client_timeout,
396 						 client->fd, POLLIN, client);
397 	client->rbc = console_ringbuffer_consumer_register(
398 		sh->console, client_ringbuffer_poll, client);
399 	if (client->rbc == NULL) {
400 		warnx("Failed to register a consumer.\n");
401 		rc = -ENOMEM;
402 		goto free_client;
403 	}
404 
405 	n = sh->n_clients++;
406 
407 	/*
408 	 * We're managing an array of pointers to aggregates, so don't warn about
409 	 * sizeof() on a pointer type.
410 	 */
411 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
412 	sh->clients =
413 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
414 	/* NOLINTEND(bugprone-sizeof-expression) */
415 	sh->clients[n] = client;
416 
417 	/* Return the second FD to caller. */
418 	return fds[1];
419 
420 free_client:
421 	free(client);
422 close_fds:
423 	close(fds[0]);
424 	close(fds[1]);
425 	return rc;
426 }
427 
socket_init(const struct handler_type * type,struct console * console,struct config * config)428 static struct handler *socket_init(const struct handler_type *type
429 				   __attribute__((unused)),
430 				   struct console *console,
431 				   struct config *config
432 				   __attribute__((unused)))
433 {
434 	struct socket_handler *sh;
435 	struct sockaddr_un addr;
436 	size_t addrlen;
437 	ssize_t len;
438 	int rc;
439 
440 	sh = malloc(sizeof(*sh));
441 	if (!sh) {
442 		return NULL;
443 	}
444 
445 	sh->console = console;
446 	sh->clients = NULL;
447 	sh->n_clients = 0;
448 
449 	memset(&addr, 0, sizeof(addr));
450 	addr.sun_family = AF_UNIX;
451 	len = console_socket_path(addr.sun_path, console->console_id);
452 	if (len < 0) {
453 		if (errno) {
454 			warn("Failed to configure socket: %s", strerror(errno));
455 		} else {
456 			warn("Socket name length exceeds buffer limits");
457 		}
458 		goto err_free;
459 	}
460 
461 	/* Try to take a socket from systemd first */
462 	if (sd_listen_fds(0) == 1 &&
463 	    sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1,
464 			      addr.sun_path, len) > 0) {
465 		sh->sd = SD_LISTEN_FDS_START;
466 	} else {
467 		sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
468 		if (sh->sd < 0) {
469 			warn("Can't create socket");
470 			goto err_free;
471 		}
472 
473 		addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
474 
475 		rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
476 		if (rc) {
477 			socket_path_t name;
478 			console_socket_path_readable(&addr, addrlen, name);
479 			warn("Can't bind to socket path %s (terminated at first null)",
480 			     name);
481 			goto err_close;
482 		}
483 
484 		rc = listen(sh->sd, 1);
485 		if (rc) {
486 			warn("Can't listen for incoming connections");
487 			goto err_close;
488 		}
489 	}
490 
491 	sh->poller = console_poller_register(console, &sh->handler, socket_poll,
492 					     NULL, sh->sd, POLLIN, NULL);
493 
494 	return &sh->handler;
495 
496 err_close:
497 	close(sh->sd);
498 err_free:
499 	free(sh);
500 	return NULL;
501 }
502 
socket_deselect(struct handler * handler)503 static void socket_deselect(struct handler *handler)
504 {
505 	struct socket_handler *sh = to_socket_handler(handler);
506 
507 	while (sh->n_clients) {
508 		struct client *c = sh->clients[0];
509 		client_drain_queue(c, 0);
510 		client_close(c);
511 	}
512 }
513 
socket_fini(struct handler * handler)514 static void socket_fini(struct handler *handler)
515 {
516 	struct socket_handler *sh = to_socket_handler(handler);
517 
518 	while (sh->n_clients) {
519 		client_close(sh->clients[0]);
520 	}
521 
522 	if (sh->poller) {
523 		console_poller_unregister(sh->console, sh->poller);
524 	}
525 
526 	close(sh->sd);
527 	free(sh);
528 }
529 
530 static const struct handler_type socket_handler = {
531 	.name = "socket",
532 	.init = socket_init,
533 	.deselect = socket_deselect,
534 	.fini = socket_fini,
535 };
536 
537 console_handler_register(&socket_handler);
538