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