1 /*
2  * Copyright (C)2018-2022 Intel Corporation.
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <sys/queue.h>
10 #include <sys/un.h>
11 #include <pthread.h>
12 #include <errno.h>
13 #include <sys/un.h>
14 #include <sys/socket.h>
15 #include <sys/stat.h>
16 #include <dirent.h>
17 #include "mevent.h"
18 #include "acrn_mngr.h"
19 
20 /* helpers */
21 /* Check if @path exists and if is a directory, if not existence, create or warn according to the flag */
check_dir(const char * path,int flags)22 int check_dir(const char *path, int flags)
23 {
24         struct stat st;
25 
26         if (stat(path, &st)) {
27                 if (flags) {
28                         if (mkdir(path, 0666)) {
29                                 perror(path);
30                                 return -1;
31                         }
32                         return 0;
33                 } else {
34                         printf("%s doesn't exist!\n", path);
35                         return -1;
36                 }
37         }
38 
39         if (S_ISDIR(st.st_mode))
40                 return 0;
41 
42         fprintf(stderr, "%s exist, and not a directory!\n", path);
43         return -1;
44 }
45 
46 
47 #define MNGR_SOCK_FMT		"/run/acrn/mngr/%s.%d.socket"
48 #define MNGR_MAX_HANDLER	8
49 #define MNGR_MAX_CLIENT		4
50 
51 #define CLIENT_BUF_LEN  4096
52 
53 struct mngr_client {
54 	/* the rest should be invisible for msg_handler */
55 	struct sockaddr_un addr;
56 	int fd;
57 	socklen_t addr_len;
58 	void *buf;
59 	int len;		/* buf len */
60 	LIST_ENTRY(mngr_client) list;
61 };
62 
63 struct mngr_handler {
64 	unsigned id;
65 	void (*cb) (struct mngr_msg * msg, int client_fd, void *priv);
66 	void *priv;
67 	LIST_ENTRY(mngr_handler) list;
68 };
69 
70 struct mngr_fd {
71 	int type;
72 	int desc;		/* unique int to this descripter */
73 				/* returned by mngr_open_un */
74 	LIST_ENTRY(mngr_fd) list;
75 
76 	/* Unix socket stuff */
77 	int fd;			/* the unix socket fd */
78 	struct sockaddr_un addr;
79 	socklen_t addr_len;
80 
81 	/* for servet */
82 	int listening;
83 	int polling;
84 	pthread_t listen_thread;	/* for connect/disconnect */
85 	pthread_t poll_thread;	/* poll requests */
86 
87 	/* a server can have many client connection */
88 	LIST_HEAD(client_list, mngr_client) client_head;	/* clients for this server */
89 	pthread_mutex_t client_mtx;
90 	int num_client;
91 
92 	/* handlers */
93 	LIST_HEAD(handler_list, mngr_handler) handler_head;	/* clients for this server */
94 	pthread_mutex_t handler_mtx;
95 };
96 
mngr_client_new(struct mngr_fd * mfd)97 static struct mngr_client *mngr_client_new(struct mngr_fd *mfd)
98 {
99 	struct mngr_client *client;
100 
101 	client = calloc(1, sizeof(*client));
102 	if (!client) {
103 		printf("%s: Failed to alloc mem for client\n", __func__);
104 		goto alloc_client;
105 	}
106 
107 	client->buf = calloc(1, CLIENT_BUF_LEN);
108 	if (!client->buf) {
109 		printf("%s: Failed to alloc mem for client buf\n", __func__);
110 		goto alloc_buf;
111 	}
112 
113 	client->addr_len = sizeof(client->addr);
114 	client->fd =
115 	    accept(mfd->fd, (struct sockaddr *)&client->addr,
116 		   &client->addr_len);
117 	if (client->fd < 0) {
118 		printf("%s: Failed to accept from fd %d, err: %s\n", __func__, mfd->fd, strerror(errno));
119 		goto accept_con;
120 	}
121 
122 	pthread_mutex_lock(&mfd->client_mtx);
123 	LIST_INSERT_HEAD(&mfd->client_head, client, list);
124 	pthread_mutex_unlock(&mfd->client_mtx);
125 
126 	return client;
127 
128  accept_con:
129 	free(client->buf);
130 	client->buf = NULL;
131  alloc_buf:
132 	free(client);
133  alloc_client:
134 	return NULL;
135 }
136 
mngr_client_free_res(struct mngr_client * client)137 static void mngr_client_free_res(struct mngr_client *client)
138 {
139 	close(client->fd);
140 	client->fd = -1;
141 	free(client->buf);
142 	client->buf = NULL;
143 	free(client);
144 }
145 
mngr_client_free(struct mngr_fd * mfd,struct mngr_client * client)146 static void mngr_client_free(struct mngr_fd *mfd, struct mngr_client *client)
147 {
148 	pthread_mutex_lock(&mfd->client_mtx);
149 	LIST_REMOVE(client, list);
150 	pthread_mutex_unlock(&mfd->client_mtx);
151 
152 	mngr_client_free_res(client);
153 }
154 
155 static LIST_HEAD(mngr_fd_list, mngr_fd) mngr_fd_head;
156 static pthread_mutex_t mngr_fd_mtx = PTHREAD_MUTEX_INITIALIZER;
157 
server_listen_func(void * arg)158 static void *server_listen_func(void *arg)
159 {
160 	struct mngr_fd *mfd = arg;
161 	struct mngr_client *client;
162 
163 	printf("Listening %d...\n", mfd->desc);
164 	while (mfd->listening) {
165 		/* wait connection */
166 		if (mfd->num_client >= MNGR_MAX_CLIENT) {
167 			usleep(500000);
168 			continue;
169 		}
170 
171 		client = mngr_client_new(mfd);
172 		if (!client) {
173 			usleep(500000);
174 			continue;
175 		}
176 		printf("Connected:%d\n", client->fd);
177 		mfd->num_client++;
178 	}
179 	printf("Stop listening %d...\n", mfd->desc);
180 	return NULL;
181 }
182 
server_parse_buf(struct mngr_fd * mfd,struct mngr_client * client)183 static int server_parse_buf(struct mngr_fd *mfd, struct mngr_client *client)
184 {
185 	struct mngr_msg *msg;
186 	struct mngr_handler *handler;
187 	size_t p = 0;
188 	int handled = 0;
189 
190 	if (client->len < sizeof(struct mngr_msg))
191 		return -1;
192 
193 	do {
194 		msg = client->buf + p;
195 
196 		/* do we out-of-boundary? */
197 		if (p + sizeof(struct mngr_msg) > client->len) {
198 			printf("%s: Out of boundary, client len: %d, p: %lu\n", __func__, client->len, p);
199 			break;
200 		}
201 
202 		LIST_FOREACH(handler, &mfd->handler_head, list) {
203 			if (msg->magic != MNGR_MSG_MAGIC)
204 				return -1;
205 			if (handler->id != msg->msgid)
206 				continue;
207 
208 			handler->cb(msg, client->fd, handler->priv);
209 			handled = 1;
210 			break;
211 		}
212 		p += sizeof(struct mngr_msg);
213 	} while (p < client->len);
214 
215 	if (!handled)
216 		fprintf(stderr, "Unknown message id: %d\n", msg->msgid);
217 
218 	return 0;
219 }
220 
server_poll_func(void * arg)221 static void *server_poll_func(void *arg)
222 {
223 	struct mngr_fd *mfd = arg;
224 	struct mngr_client *client;
225 	fd_set rfd;
226 	int max_fd = 0;
227 	struct timeval timeout;
228 	struct mngr_client *poll_client[MNGR_MAX_CLIENT];
229 	int nfd, i;
230 
231 	printf("polling %d...\n", mfd->desc);
232 	while (mfd->polling) {
233 		max_fd = 0;
234 		nfd = 0;
235 		pthread_mutex_lock(&mfd->client_mtx);
236 		FD_ZERO(&rfd);
237 		LIST_FOREACH(client, &mfd->client_head, list) {
238 			FD_SET(client->fd, &rfd);
239 			poll_client[nfd] = client;
240 			nfd++;
241 			if (client->fd > max_fd)
242 				max_fd = client->fd;
243 		}
244 		pthread_mutex_unlock(&mfd->client_mtx);
245 
246 		timeout.tv_sec = 0;
247 		timeout.tv_usec = 10000;
248 		select(max_fd + 1, &rfd, NULL, NULL, &timeout);
249 
250 		for (i = 0; i < nfd; i++) {
251 			client = poll_client[i];
252 			if (!FD_ISSET(client->fd, &rfd))
253 				continue;
254 			client->len =
255 			    read(client->fd, client->buf, CLIENT_BUF_LEN);
256 			if (client->len <= 0) {
257 				fprintf(stderr, "Disconnect(%d)!\r\n",
258 					client->fd);
259 				mngr_client_free(mfd, client);
260 				mfd->num_client--;
261 				continue;
262 			}
263 			if (client->len == CLIENT_BUF_LEN) {
264 				fprintf(stderr, "TODO: buf overflow!\r\n");
265 				continue;
266 			}
267 
268 			server_parse_buf(mfd, client);
269 		}
270 	}
271 	printf("Stop polling %d...\n", mfd->desc);
272 
273 	return NULL;
274 }
275 
desc_to_mfd_nolock(int val)276 static struct mngr_fd *desc_to_mfd_nolock(int val)
277 {
278 	struct mngr_fd *fd;
279 	struct mngr_fd *find = NULL;
280 
281 	LIST_FOREACH(fd, &mngr_fd_head, list)
282 	    if (val == fd->desc) {
283 		find = fd;
284 		break;
285 	}
286 
287 	return find;
288 }
289 
290 /* Does this integer number has a mngr_fd behind? */
desc_to_mfd(int val)291 static struct mngr_fd *desc_to_mfd(int val)
292 {
293 	struct mngr_fd *find = NULL;
294 
295 	pthread_mutex_lock(&mngr_fd_mtx);
296 	find = desc_to_mfd_nolock(val);
297 	pthread_mutex_unlock(&mngr_fd_mtx);
298 
299 	return find;
300 }
301 
create_new_server(const char * name)302 static int create_new_server(const char *name)
303 {
304 	struct mngr_fd *mfd;
305 	int ret;
306 	char path[128] = { };
307 
308 	if (snprintf(path, sizeof(path), MNGR_SOCK_FMT, name, getpid()) >= sizeof(path)) {
309 		printf("WARN: the path is truncated\n");
310 		return -1;
311 	}
312 
313 	mfd = calloc(1, sizeof(*mfd));
314 	if (!mfd) {
315 		perror("Alloc struct mngr_fd");
316 		ret = errno;
317 		goto alloc_mfd;
318 	}
319 	pthread_mutex_init(&mfd->client_mtx, NULL);
320 	mfd->type = MNGR_SERVER;
321 
322 	/* Socket stuff */
323 	unlink(path);
324 	mfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
325 	if (mfd->fd < 0) {
326 		printf("%s: Failed to call socket, err: %s\n", __func__, strerror(errno));
327 		ret = mfd->fd;
328 		goto sock_err;
329 	}
330 	mfd->addr.sun_family = AF_UNIX;
331 	strncpy(mfd->addr.sun_path, path, sizeof(mfd->addr.sun_path));
332 
333 	ret = bind(mfd->fd, (struct sockaddr *)&mfd->addr, sizeof(mfd->addr));
334 	if (ret < 0) {
335 		printf("%s: Failed to bind fd %d, err: %s\n", __func__, mfd->fd, strerror(errno));
336 		goto bind_err;
337 	}
338 	listen(mfd->fd, 1);
339 
340 	/* create a listen_thread */
341 	mfd->listening = 1;
342 	ret =
343 	    pthread_create(&mfd->listen_thread, NULL, server_listen_func, mfd);
344 	if (ret < 0) {
345 		printf("%s: Failed to create listen_thread, err: %s\n", __func__, strerror(errno));
346 		goto listen_err;
347 	}
348 	pthread_setname_np(mfd->listen_thread, "mngr_listen");
349 
350 	/* create a poll_thread */
351 	mfd->polling = 1;
352 	ret = pthread_create(&mfd->poll_thread, NULL, server_poll_func, mfd);
353 	if (ret < 0) {
354 		printf("%s: Failed to create poll_thread, err: %s\n", __func__, strerror(errno));
355 		goto poll_err;
356 	}
357 	pthread_setname_np(mfd->poll_thread, "mngr_pull");
358 
359 	mfd->desc = mfd->fd;
360 	/* add this to mngr_fd_head */
361 	pthread_mutex_lock(&mngr_fd_mtx);
362 	LIST_INSERT_HEAD(&mngr_fd_head, mfd, list);
363 	pthread_mutex_unlock(&mngr_fd_mtx);
364 
365 	return mfd->desc;
366 
367  poll_err:
368 	mfd->listening = 0;
369 	pthread_join(mfd->listen_thread, NULL);
370  listen_err:
371 	unlink(path);
372  bind_err:
373 	close(mfd->fd);
374  sock_err:
375 	free(mfd);
376  alloc_mfd:
377 	return ret;
378 }
379 
close_server(struct mngr_fd * mfd)380 static void close_server(struct mngr_fd *mfd)
381 {
382 	struct mngr_client *client, *tclient;
383 	struct mngr_handler *handler, *thandler;
384 
385 	shutdown(mfd->fd, SHUT_RDWR);
386 
387 	mfd->listening = 0;
388 	pthread_join(mfd->listen_thread, NULL);
389 
390 	mfd->polling = 0;
391 	pthread_join(mfd->poll_thread, NULL);
392 
393 	pthread_mutex_lock(&mfd->client_mtx);
394 	list_foreach_safe(client, &mfd->client_head, list, tclient) {
395 		LIST_REMOVE(client, list);
396 		mngr_client_free_res(client);
397 	}
398 	pthread_mutex_unlock(&mfd->client_mtx);
399 
400 	pthread_mutex_lock(&mfd->handler_mtx);
401 	list_foreach_safe(handler, &mfd->handler_head, list, thandler) {
402 		LIST_REMOVE(handler, list);
403 		free(handler);
404 	}
405 	pthread_mutex_unlock(&mfd->handler_mtx);
406 
407 	unlink(mfd->addr.sun_path);
408 	close(mfd->fd);
409 
410 	free(mfd);
411 }
412 
connect_to_server(const char * name)413 static int connect_to_server(const char *name)
414 {
415 	struct mngr_fd *mfd;
416 	int ret;
417 	DIR *dir;
418 	char *s_name = NULL, *p = NULL;
419 	struct dirent *entry;
420 
421 	dir = opendir("/run/acrn/mngr");
422 	if (!dir) {
423 		printf("%s: Failed to open directory /run/acrn/mngr\n", __func__);
424 		return -1;
425 	}
426 
427 	while ((entry = readdir(dir))) {
428 		p = strchr(entry->d_name, '.');
429 		if (!p || p == entry->d_name)
430 			continue;
431 		else
432 			ret = p - entry->d_name;
433 
434 		if (!strncmp(entry->d_name, name, ret)) {
435 			s_name = entry->d_name;
436 			break;
437 		}
438 	}
439 
440 	if (!s_name) {
441 		printf("%s: Can't find %s\n", __func__, name);
442 		closedir(dir);
443 		return -1;
444 	}
445 
446 	mfd = calloc(1, sizeof(*mfd));
447 	if (!mfd) {
448 		perror("Alloc struct mngr_fd");
449 		ret = errno;
450 		goto alloc_mfd;
451 	}
452 
453 	mfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
454 	if (mfd->fd < 0) {
455 		printf("%s %d\n", __FUNCTION__, __LINE__);
456 		ret = -1;
457 		goto sock_err;
458 	}
459 
460 	mfd->addr.sun_family = AF_UNIX;
461 	ret = snprintf(mfd->addr.sun_path, sizeof(mfd->addr.sun_path),
462 		 "/run/acrn/mngr/%s", s_name);
463 	if (ret >= sizeof(mfd->addr.sun_path))
464 		printf("WARN: %s is truncated\n", s_name);
465 
466 	ret =
467 	    connect(mfd->fd, (struct sockaddr *)&mfd->addr, sizeof(mfd->addr));
468 	if (ret < 0) {
469 		printf("%s %d\n", __FUNCTION__, __LINE__);
470 		goto connect_err;
471 	}
472 
473 	mfd->desc = mfd->fd;
474 	/* add this to mngr_fd_head */
475 	pthread_mutex_lock(&mngr_fd_mtx);
476 	LIST_INSERT_HEAD(&mngr_fd_head, mfd, list);
477 	pthread_mutex_unlock(&mngr_fd_mtx);
478 
479 	closedir(dir);
480 	return mfd->desc;
481 
482  connect_err:
483 	close(mfd->fd);
484  sock_err:
485 	free(mfd);
486  alloc_mfd:
487 	closedir(dir);
488 	return ret;
489 }
490 
close_client(struct mngr_fd * mfd)491 static void close_client(struct mngr_fd *mfd)
492 {
493 	close(mfd->fd);
494 	free(mfd);
495 }
496 
mngr_open_un(const char * name,int flags)497 int mngr_open_un(const char *name, int flags)
498 {
499 	check_dir(ACRN_DM_BASE_PATH, CHK_ONLY);
500 	check_dir(ACRN_DM_SOCK_PATH, CHK_ONLY);
501 
502 	if (!name) {
503 		printf("%s: No socket name configured\n", __func__);
504 		return -1;
505 	}
506 
507 	switch (flags) {
508 	case MNGR_SERVER:
509 		return create_new_server(name);
510 	case MNGR_CLIENT:
511 		return connect_to_server(name);
512 	default:
513 		printf("%s: Unknow flag %d\n", __func__, flags);
514 	}
515 
516 	return -1;
517 }
518 
mngr_close(int val)519 void mngr_close(int val)
520 {
521 	struct mngr_fd *mfd;
522 
523 	mfd = desc_to_mfd(val);
524 	if (!mfd) {
525 		printf("%s: No mngr_fd binded to fd %d\n", __func__, val);
526 		return;
527 	}
528 
529 	pthread_mutex_lock(&mngr_fd_mtx);
530 	LIST_REMOVE(mfd, list);
531 	pthread_mutex_unlock(&mngr_fd_mtx);
532 
533 	switch (mfd->type) {
534 	case MNGR_SERVER:
535 		close_server(mfd);
536 		break;
537 	case MNGR_CLIENT:
538 		close_client(mfd);
539 		break;
540 	default:
541 		printf("%s: Unknown mfd type %d\n", __func__, mfd->type);
542 	}
543 
544 }
545 
mngr_add_handler(int server_fd,unsigned id,void (* cb)(struct mngr_msg * msg,int client_fd,void * param),void * param)546 int mngr_add_handler(int server_fd, unsigned id,
547 		     void (*cb) (struct mngr_msg * msg, int client_fd,
548 				 void *param), void *param)
549 {
550 	struct mngr_fd *mfd;
551 	struct mngr_handler *handler;
552 
553 	mfd = desc_to_mfd(server_fd);
554 	if (!mfd) {
555 		printf("%s: No mngr_fd binded to fd %d\n", __func__, server_fd);
556 		return -1;
557 	}
558 
559 	handler = calloc(1, sizeof(*handler));
560 	if (!handler) {
561 		printf("%s: Failed to alloc mem for handler\n", __func__);
562 		return -1;
563 	}
564 
565 	handler->id = id;
566 	handler->cb = cb;
567 	handler->priv = param;
568 
569 	pthread_mutex_lock(&mfd->handler_mtx);
570 	LIST_INSERT_HEAD(&mfd->handler_head, handler, list);
571 	pthread_mutex_unlock(&mfd->handler_mtx);
572 
573 	return 0;
574 }
575 
mngr_send_msg(int fd,struct mngr_msg * req,struct mngr_msg * ack,unsigned timeout)576 int mngr_send_msg(int fd, struct mngr_msg *req, struct mngr_msg *ack,
577 		  unsigned timeout)
578 {
579 	int socket_fd = fd;
580 	fd_set rfd, wfd;
581 	struct timeval t;
582 	int ret;
583 
584 	if (!req) {
585 		printf("%s %d\n", __FUNCTION__, __LINE__);
586 		return -1;
587 	}
588 
589 	t.tv_sec = timeout;
590 	t.tv_usec = 0;
591 
592 	FD_ZERO(&rfd);
593 	FD_ZERO(&wfd);
594 	FD_SET(socket_fd, &rfd);
595 	FD_SET(socket_fd, &wfd);
596 
597 	if (timeout)
598 		select(socket_fd + 1, NULL, &wfd, NULL, &t);
599 	else
600 		select(socket_fd + 1, NULL, &wfd, NULL, NULL);
601 
602 	if (!FD_ISSET(socket_fd, &wfd)) {
603 		printf("%s %d\n", __FUNCTION__, __LINE__);
604 		return -1;
605 	}
606 
607 	ret = write(socket_fd, req, sizeof(struct mngr_msg));
608 	if (ret != sizeof(struct mngr_msg)) {
609 		printf("%s %d\n", __FUNCTION__, __LINE__);
610 		return -1;
611 	}
612 
613 	if (!ack)
614 		return 0;
615 
616 	if (timeout)
617 		select(socket_fd + 1, &rfd, NULL, NULL, &t);
618 	else
619 		select(socket_fd + 1, &rfd, NULL, NULL, NULL);
620 
621 	if (!FD_ISSET(socket_fd, &rfd)) {
622 		printf("%s %d\n", __FUNCTION__, __LINE__);
623 		return -1;
624 	}
625 
626 	ret = read(socket_fd, ack, sizeof(struct mngr_msg));
627 
628 	return ret;
629 }
630